FUNCTIONAL PROGRAMMING STRIKES BACK

WE NEED TO TAKE A STEP BACK

Alonzo Church

LAMBDA FUNCTIONS

I BET YOU'RE ALREADY USING THEM

``λx.x+x``
``lambda x: x + x``

Lambda Calculus

Python

LAMBDA FUNCTIONS

I BET YOU'RE ALREADY USING THEM

``λx.x+x``
``(x) => x + x;``

Lambda Calculus

JavaScript

``````λx.λy.x  ;true
λx.λy.y  ;false``````
``````const TRUE  = x => y => x;
const FALSE = x => y => y;``````

Lambda Calculus

JavaScript

BOOLEANS?

WHO NEEDS BOOLEANS?

``λz.(λx.(λy.zxy)) ;if/then/else``
``const IF = COND => THEN => ELSE => COND(THEN)(ELSE);``

Lambda Calculus

CONTROL STRUCTURES?

WHO NEEDS THEM?

JavaScript

PURE FUNCTIONS, PURE CODEBASE

NON-PURE FUNCTIONAL LANGUAGES EXAMPLES

``````let approved = [];

for (let i = 0; i < users.length; i++) {
if (users[i].score >= 7) {
approved.push(approved);
}
}``````
``````const approved = users.filter((user) => user.score >= 7);
``````

Mutates a value

Does not mutate a value

PURITY MEANS

IMMUTABILITY

``````let user = { name: "John" };

user.lastName = "Doe";
};``````
``const addLastName = (obj, lastName) => ({ ...obj, lastName });``

Causes a side effect

Does not cause a side effect

PURITY MEANS

NO SIDE EFFECTS

``````let result = 1;

for (let i = 2; i <= 5; i++) {
result *= i;
}

console.log('Fact of 5: ', result);``````
``````const fact = n => n === 0 ? 1 : n * fact(n - 1);

console.log(`Fact of 5: \${fact(5)}`);``````

Uses loops

Uses recursion

PURITY MEANS

NO LOOPS

``````import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Main {

public static void main(String[] args) {

List<String> numbers = Arrays.asList("1", "2", "3", "4", "5", "6");

List<Integer> even = numbers.stream()
.map(s -> Integer.valueOf(s))
.filter(number -> number % 2 == 0)
.collect(Collectors.toList());

System.out.println("Even numbers in list: " + even);
}

}``````

PURITY MEANS

NO LOOPS

``````import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Main {

public static void main(String[] args) {

List<String> numbers = Arrays.asList("1", "2", "3", "4", "5", "6");

Integer sum = numbers.stream()
.map(s -> Integer.valueOf(s))
.reduce(0, (x, y) -> x + y);

System.out.println("Sum of list is: " + sum);
}

}``````

PURITY MEANS

NO LOOPS

``````let x = 10;

return num + x;
}``````
``````function addX(num) {
const x = 10;
return num + x;
}``````

Result may change over time due to mutability

PURITY MEANS

REFERENTIAL TRANSPARENCY

Always produces the same result when the same arguments are given

``````let myCounter = 0;

while (true) {
...
myCounter++;
};``````
``````function statelessCounter(iterations) {
...
return statelessCounter(iteration + 1);
}``````

Updates the state on each iteration

PURITY MEANS

NO STATE

Creates a new "state" with every recursive function call

PURE FUNCTIONS, PURE CODEBASE

PURE FUNCTIONAL LANGUAGES EXAMPLES

``````greet :: [Char]
greet = "Hello World!"``````

"greet" is a function that returns a list of chars

PURITY MEANS

NO ASSIGNMENT STATEMENTS

``````main :: IO()
main = putStrLn "Hello World!"``````

Logging a string to the I/O means mutating the I/O stream

``````import System.Random

main = replicateM 10 (randomIO :: IO Float) >>= print``````

No randomness

PURITY MEANS

NO SIDE EFFECTS AT ALL

``````template <typename T>
void qsort (T *result, T *list, int n)
{
if (n == 0) return;
T *smallerList, *largerList;
smallerList = new T[n];
largerList = new T[n];
T pivot = list[0];
int numSmaller=0, numLarger=0;
for (int i = 1; i < n; i++)
if (list[i] < pivot)
smallerList[numSmaller++] = list[i];
else
largerList[numLarger++] = list[i];

qsort(smallerList,smallerList,numSmaller);
qsort(largerList,largerList,numLarger);

int pos = 0;
for ( int i = 0; i < numSmaller; i++)
result[pos++] = smallerList[i];

result[pos++] = pivot;

for ( int i = 0; i < numLarger; i++)
result[pos++] = largerList[i];

delete [] smallerList;
delete [] largerList;
};``````

QuickSort algorithm in C++

WHY PURITY MATTERS

PURE FUNCTIONS ARE EASIER TO REASON ABOUT

``````qsort :: Ord a => [a] -> [a]
qsort []     = []
qsort (x:xs) = qsort smaller ++ [x] ++ qsort bigger
where
smaller = filter (<  x) xs
bigger  = filter (>= x) xs``````

WHY PURITY MATTERS

PURE FUNCTIONS ARE EASIER TO REASON ABOUT

``````qsort :: Ord a => [a] -> [a]
qsort []     = []
qsort (x:xs) = qsort smaller ++ [x] ++ qsort bigger
where
smaller = filter (<  x) xs
bigger  = filter (>= x) xs``````

WHY PURITY MATTERS

PURE FUNCTIONS ARE EASIER TO REASON ABOUT

``````function callPizzeria(phone: number): void { ... };
function waitForPizza(patience: any): void { ... };``````

Testing functions with side effects

WHY PURITY MATTERS

TESTING IS EASIER

``````test("Testing a method that has an hidden state and side-effects", () => {

callPizzeria(phone);
waitForPizza(patience);
drinkBeer(can);

let pizza = getPizzaFromPizzaboy(cash);

expect(pizza).toBe(expectedPizza);
});``````
``````test("Testing a pure function is easier", () => {

const result = compose( addOne, multiplyBy5, subtract5 )(10);

expect(result).tobe(26);

});``````

Testing functions without side effects

WHY PURITY MATTERS

TESTING IS EASIER

``````def quicksort([]), do: []
def quicksort([pivot|t]) do
quicksort(for x <- t, x < pivot, do: x)
++ [pivot] ++
quicksort(for x <- t, x >= pivot, do: x)
end
``````

Quicksort algorithm in Elixir

WHY PURITY MATTERS

DEBUGGING IS EASIER

``````qsort([]) -> [];
qsort([Pivot|Rest]) ->
qsort([ X || X <- Rest, X < Pivot])
++ [Pivot] ++
qsort([ Y || Y <- Rest, Y >= Pivot]).``````

Quicksort algorithm in Erlang

WHY PURITY MATTERS

DEBUGGING IS EASIER

``````let rec quicksort =
function
| [] -> []
| x::xs ->
let (smaller,larger) = List.partition (fun y  -> y < x) xs in
(quicksort smaller) @ (x :: (quicksort larger))``````

Quicksort algorithm in OCaml

WHY PURITY MATTERS

DEBUGGING IS EASIER

``````let rec qsort = function
hd :: tl ->
let less, greater = List.partition ((>=) hd) tl
List.concat [qsort less; [hd]; qsort greater]
| _ -> []``````

Quicksort algorithm in F#

WHY PURITY MATTERS

DEBUGGING IS EASIER

``````(defn quicksort [seq]
(if (emtpy? seq) []
(let [x  (first seq)
xs (rest seq)]
(concat (quicksort (filter (fn [v] (<= v x)) xs))
[x]
(quicksort (filter (fn [v] (> v x)) xs))))))``````

Quicksort algorithm in Clojure

WHY PURITY MATTERS

DEBUGGING IS EASIER

``````def qsort: List[Int] => List[Int] = {
case Nil => Nil
case pivot :: tail =>
val (smaller, rest) = tail.partition(_ < pivot)
qsort(smaller) ::: pivot :: qsort(rest)
}``````

Quicksort algorithm in Scala

WHY PURITY MATTERS

DEBUGGING IS EASIER

WHY PURITY MATTERS

OUT-OF-THE BOX CONCURRENCY

WHY PURITY MATTERS

OUT-OF-THE BOX CONCURRENCY

``````import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Main {

public static void main(String[] args) {

List<String> numbers = Arrays.asList("1", "2", "3", "4", "5", "6");

Integer sum = numbers.parallelStream()
.map(s -> Integer.valueOf(s))
.reduce(0, (x, y) -> x + y);

System.out.println("Sum of list is: " + sum);
}

}``````

PURITY MEANS

OUT-OF-THE BOX CONCURRENCY

PURE FUNCTIONS ARE

DETERMINISTIC

``````f (x) -> x + x

g (y) -> Y * y

h (z) -> z + 2``````

PURE FUNCTIONS ARE

COMPOSABLE

``````f (x) -> x + x

g (y) -> Y * y

h (z) -> z + 2

k (x) -> f(g(h(x)))``````

PURE FUNCTIONS ARE

DECLARATIVE

``````double   (x) -> x + x

pow      (y) -> Y * y

addTwo   (z) -> z + 2

PURE FUNCTIONS ARE

DECLARATIVE

``````double   (x) -> x + x

pow      (y) -> Y * y

addTwo   (z) -> z + 2

makeMath (x) -> {

result = 0

result = double(x)
result = pow(result)

return result
}``````

Declarative? Do you have any examples?

PURE FUNCTIONS ARE

DECLARATIVE

If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.

Project Euler, Problem #1 - https://projecteuler.net/problem=1

PURE FUNCTIONS ARE

DECLARATIVE

``````public class Main {

public static void main(String[] args) {

int i, sum = 0;

for ( i = 3; i < 1000; i++) {

if (i % 3 == 0 || i % 5 == 0 ) {
sum += i;
}
}

System.out.print(sum);
}

}``````

PURE FUNCTIONS ARE

DECLARATIVE

``````import Data.List (union)

solution :: Int
solution = sum \$ [3,6..limit] `union` [5,10..limit]
where limit = 999

main :: IO()
main = print \$ solution``````

PURE FUNCTIONS ARE

DECLARATIVE

``````def solution():
return sum([i for i in range(1, 1000)
if i % 3 == 0 or i % 5 == 0])``````

PURE FUNCTIONS ARE

DECLARATIVE

``````const solution = [...Array(1000)]
.map((_, i) => i)
.filter(x => x % 3 === 0 || x % 5 === 0)
.reduce((sum, x) => sum + x, 0);``````

PURE FUNCTIONS ARE

DECLARATIVE

``````const sum         = (x, y)   => x + y;
const isModZero   = (x, y)   => x % y === 0;
const or          = (x, y)   => (x || y);
const createArray = (length) => [...Array(length)].map((_, i) => i);

const solution = (limit) => (
createArray(limit)
.filter(x => or(isModZero(x, 5), isModZero(x, 3)))
.reduce(sum, 0)
);

const result = solution(1000);``````
• Extremely mature and battle-tested
• Extremely Resilient
• 99.999999999 (nine nines) uptime

ERLANG

Used at

Used to build

• Extremely mature and battle-tested
• Extremely Resilient
• 99.999999999 (nine nines) uptime

ERLANG

• Extremely mature and battle-tested
• Incredible Type System
• Purely Functional

Used at

• Incredibly Fast
• Compiler targets everything
• Extremely mature and battle-tested

OCAML

Used at

• Runs on JVM
• Built to scale
• Great JVM interop

SCALA

Used at

Ruby

Java

JavaScript

.NET

I want to write rock solid frontend

I want to start from scratch

Clojure

Scala

ReasonML

F#

Elm

PureScript

Elixir

So should I get rid of my existing OOP/imperative code and refactor everything in a functional language?

So should I get rid of my existing OOP/imperative code and refactor everything in a functional language?

"Don't be a functional programmer.
Dont' be an object programmer.
Be a better programmer.
"

Brian Goetz, Java Language Architect at Oracle

MICHELE RIVA

Software Engineer at

Openmind

Founder of

JSMonday.dev

@MicheleRiva

@MicheleRivaCode

www.micheleriva.it

ciao@micheleriva.it

By Michele Riva

Stack Wars

Functional programming strikes back!

• 642