How to talk like a Functional Programmer

Posted on May 23, 2019

When we speak without jargon, it frees us from hiding behind knowledge we don’t have.

Richard Feynman

Before we begin

This is a short introduction to Functional Programing in which we will learn:

  • that FPFunctional Programming

    is easy, fun and definitely not scary
  • few new words and essential conceptsImportant terms and concepts will be marked in bold

  • how to be kind and not make fun of insane people

What is Functional Programming

Functional programming is programming with functions. And the best thing about functions is that they always do the same thing. This is not always the case with methods, procedures, and all other terms used in computer science to name a piece of executable code.

If you have written some code before, maybe you already wrote some functions without knowing. So how to spot the difference? What are the properties of this magical and mysterious function?

  • totality – it returns a value for every possible input.
  • determinism – it returns the same value for the same input
  • purity – invoking it produces no observable effect other than the result it returns

Whoa, whoa, whoa! Hold your horses governor! You said that FP is easy and fun 😢😢😢, and now you are saying things that sound like math, and math is scary!

Climate change and flat-earthers are scary, not math. Keep your cool, apply the three properties, and you are already a functional programmer. Easy. And since seeing is believing, here is an exampleFor all examples in this blog post I will be using the kotlin programming language.

fun function(a: Int): Int {
    return a + 1
}

fun method(a: Int): Int {
    val inMood = Random().nextBoolean()

    if (inMood) {
       return a + 1
    } else {
        println("really not in mood today")
        return a
    }
}

Q: Is function total ?
A: Yes. It will always return a value for every input.

Q: Is function deterministic ?
A: Yes. It will always return the same value for the same input.

Q: Is function pure ?
A: Yes. Its only effect is the computation of the new return value.

I will leave trying to answer the same questions about method as an exercise for the reader.
And now it’s time for the So what? question.

Q: So what 😒 ?
A: You will sleep better at night, have more free time and cool things to talk about. Plus you can be finally sure of something else beside that the Earth is not flat – that your code can be reasonedthe action of thinking about something in a logical, sensible way:
“he explained the reasoning behind printing the users cleartext passwords in the logs”

about.


val two = function (1)
val referentiallyTransparent = two == 2

If a function is total , deterministic and pure it is also referentially transparentAn expression is called referentially transparent if it can be replaced with its
corresponding value without changing the program’s behavior.
See the full article on
wikipedia.

. Meaning it can be replaced with its corresponding value without changing the program’s behavior. So we can safely substitute function(1) everywhere in our program with 2 and the program will not change.

So we can use one term instead of three to name a function that can be reasoned about, and we are already getting the hang of the FP jargon.

What is immutable may never change

The next important concept in fp is immutability. Immutable variablesfinal, val , const , readonly, etc

helps us write functions that are deterministic.

Q: Why 😒?
A: Because it prevents us from keeping a shared state somewhere.

Q: What 😒?
A: Answering a question about an unknown term with another unknown term is definitely not how it should be done. Let’s see some examples.

var counter = 0

fun incrementAndGet(): Int {
    counter = counter+1
    return counter
}

The shared state here is the variable counter. We cannot determine what result we are going to get from calling incrementAndGet just by looking at the code any more. We cannot reason about it, and if incrementAndGet is called concurrently from multiple threadsmultithreading is the ability of a central processing unit (CPU) (or a single core in a
multi-core processor) to provide multiple threads of execution concurrently.
See the full article on wikipedia.

- it will become a real mess.

So what can we do? Here is one way of doing it:

data class ImmutableCounter(val counter: Int)

fun incrementAndGet(old: ImmutableCounter): ImmutableCounter {
    return old.copy(counter = old.counter + 1)
}

Instead of changing a variable we can create a new copyIt’s often the case that we need to copy an object altering some of its properties, but keeping the rest unchanged. This is what the copy function does.

. This makes
incrementAndGet deterministic again.

Dealing with shared mutable state is hard. Even with FP. The trick is to push it far away to the edge of the program as possible. Meaning having only few functions that deal with it.

In future chapters, when we’ve grown our little FP muscles we will see how to turn non-deterministic and non-pure code referentially-transparent again.

Errors and exceptions

We’ve mostly talked about determinism but not about totality until now. Totality meant that a function must return a value for every possible input. Non-total functions are called partial functions

Even advanced pure fp languages have runtime errors. Which implies that their functions are partial. But being pragmatic people, we accept the fact and move on, because runtime errors are usually due to a programming error, so it’s best to let them crash the program and then fix them.

@Throws(IOException::class)
fun saveToFile(path:String, content: String) : Int 

Most languages have the notion of checked exceptions. In the case of saveToFile a function that returns the number of bytes written to disk as Int , the @throws clause changes the return type from Int to either IOException if something goes wrong or Int if all is okay. But it still leaves the function total. It makes us deal with exceptions using a special syntax – things like catch , throw and the lot, but the function is expected to return value for every possible input – only in one of the cases the value will be the exception.

fun saveToFile(path:String, content: String) : Either<IOException,Int>

/* or */

fun saveToFile(path:String, content: String) : Result<IOException,Int> 

Many fp programmers like to keep it simple and explicit, and use things like Either or Result to place the exception back into the return type of the function. This way they can deal with exceptions just like regular data and not use any special syntax. Either and Result have methods like isError,isOk,getOk,getError that let us check if they contain an error or the expected result and ways to extract it.

How to be kind and not make fun of insane people

A lot of FP programmers like to use the word sane for code that can be reasoned about. Since most imperativeimperative programming is a programming paradigm that uses statements that change a program’s state

and object-orientedobject-oriented programming is not something set in stone, and even it’s practitioners tend to disagree on the common set of properties that define it

code is not referentially-transparent, it is not uncommon to see the fp crowd riding their high horses and shouting insane all around. I will try to avoid using the term sanereferentially-transparent is so much mentally superior and arrogantly kewler then sane

, not fuel the Us vs Them thinking, or bring the topic of language superiority in your face. I do not want to prevent good folk from trying new things by feeling scared or inferior.

One can program functionally with java, or program imperatively with haskell. The two are not linked, though it helps to have things like a advanced type system and immutable variables baked into the language.

P.S

People presume that programmers always write correct code. They don’t. Expect plane crashes, money gone and wrong climate change data. But I truly believe that functional programming is the one way forward.

This blog post is always a work in progress. I will keep adding more chapters while working on my other series, extracting any generic terms and concepts here.

I am really hoping that this blog post left you wiser than before. If it does not – reach me at twitter and show me what can we improve.