# What is a function?

Functions in the mathematical sense

A function takes input(s) and definitely always has a return value.

Β f(x) = 2x + 3

``````function fn(x) {
return 2 * x + 3;
}
``````
``````function p1() {
return 'something';
}

function p2(x) {
const y = x + 1;
}
``````

β

π

## Word: Arity

``````// unary
function foo(x) {
// ..
}

foo.length; // 1
``````
``````// binary
function foo(x, y) {
// ..
}

foo.length; // 2
``````
``````// trinary
function foo(x, y, z) {
// ..
}

foo.length; // 3
``````

# Side-effects

``````var y;
function f(x) {
y = (2 * Math.pow( x, 2 )) + 3;
}

f(2);
y; // 11
``````
``````function f(x) {
return (2 * Math.pow( x, 2 )) + 3;
}

var y = f( 2 );
y; // 11
``````

# Side-effects

``````function sum(list) {
var total = 0;
for (let i = 0; i < list.length; i++) {
if (!list[i]) list[i] = 0;
total = total + list[i];
}

}

var nums = [ 1, 3, 9, 27, , 84 ];
sum( nums ); // 124
``````

Is this code problematic? π€

A function with no side causes/effects is called a pure function. A pure function is idempotent in the programming sense, because it cannot have any side effects.

## Which is pure

``````function add(x,y) {
return x + y;
}
``````
``````const PI = 3.141592;

}

return height * circleArea( radius );
}
``````

β

β

## 2 Words: ReferentialTransparency

Referential transparency is the assertion that a function call could be replaced by its output value, and the overall program behavior wouldnβt change.

Pure functions have referential transparency

# Higher Order Functions

Functions of Functions

### Higher Order Functions

``````function forEach(list,fn) {
for (let v of list) {
fn(v);
}
}

forEach([1,2,3,4,5], (val) => {
console.log(val);
});
``````

### Higher Order Functions

``````function foo() {
return function inner(msg) {
return msg.toUpperCase();
};
}``````

# Closures

Closure is when a function remembers and accesses variables from outside of its own scope, even when that function is executed in a different scope.

## Closures

``````function counter (start) {
var val = start;
return function current(increment = 1){
val = val + increment;
return val;
};
}

const myCounter = counter(0);

myCounter(); // 1
myCounter(); // 2
myCounter(); // 3
``````

## Closures

``````function incrementBy (inc) {
return function (value) {
return value + inc;
}
}

const increment = incrementBy(1);
const increment2 = incrementBy(2);
const increment3 = incrementBy(3);

increment(5); // 6
increment2(5); // 7
increment3(5); // 8
``````

Β is the process of taking a function with multiple arguments and returning a series of functions that take one argument and eventually resolve to a value.

# Currying

``````function volume(l, w, h) {
return l * w * h;
}

// curried
function volume1(length) {
return function(width) {
return function(height) {
return height * width * length;
}
}
}

volume(2,3,4); // 24
volume1(2)(3)(4); // 24
``````

## Currying

``````function curry(fn) {

return (function nextCurried(prevArgs) {

return function curried(nextArg) {
var args = [...prevArgs, nextArg];

if (args.length >= fn.length) {
return fn(...args);
}

return nextCurried(args);
};

})([]);
}
``````

# Composing Functions

### Composing Functions

``````function clap (str) {
return str.split(' ').join(' π ');
}

function scream (str) {
return str.toUpperCase();
}

clap(
scream(
'Hello World!'
) // HELLO WORLD
) // HELLO π WORLD

const louder = compose(clap, scream);

louder('Hello World!') // HELLO π WORLD
``````

### basic compose()

``````function compose2(fn2, fn1) {
return function composed(origValue) {
return fn2(fn1(origValue));
};
}
``````

finalValue <-- func1 <-- func2 <-- ... <-- funcN <-- origValue

What if we want to compose more than two functions?

## compose()

``````function compose(...fns) {
return fns.reverse().reduce((fn1,fn2) => {
return function composed(...args){
return fn2( fn1( ...args ) );
};
});
}
``````

# Order Matters!

## ππππ

Order of operations is not Omni-directional in most cases

``````function add (x) {
return x + 3;
}

function mul (x) {
return x * 4;
}

c1(5) !== c2(5);
``````
``````function pipe(...fns) {
return fns.reduce((fn1,fn2) => {
return function piped(...args){
return fn2( fn1( ...args ) );
};
});
}
``````

# Point-free style

## Point Free

``````function double(x) {
return x * 2;
}

[1,2,3,4,5].map(v => {
return double(v);
});
``````
``````function double(x) {
return x * 2;
}

[1,2,3,4,5].map(double);
``````
``````["1","2","3"].map(v => {
return parseInt(v);
});
``````

## Point Free ALL THE THINGS!

``````["1","2","3"].map(parseInt);
``````

β¬

π

## unary()

``````function unary (fn) {
return function (arg) {
return fn(arg);
}
}
``````

Locks the arity to 1

``````["1","2","3"].map(unary(parseInt));
``````

# Immutability and Side Effects

Immutability plays a large role when building pure functions

``````function reverse (arr) {
return [...arr].reverse();
}

let arr = [1, 2, 3, 4, 5];
reverse(arr);
``````
``````function reverse (arr) {
return arr.reverse();
}

let arr = [1, 2, 3, 4, 5];
reverse(arr);
``````

## Immutability with Objects

``````function process (obj) {
const newObj = { ...obj };

// DO stuff
return newObj;
}

const obj = {
a: 12,
b: 'hello world',
c: { x: 0, y: 10 }
};

process(obj);
``````

## Immutability with Objects

``````function process (obj) {
const newObj = { ...obj, c: { ...obj.c } };

// DO stuff
return newObj;
}

const obj = {
a: 12,
b: 'hello world',
c: { x: 0, y: 10 }
};

process(obj);
``````

Deep

# Immer

``````import produce from "immer"

const baseState = [
{
todo: "Learn typescript",
done: true
},
{
todo: "Try immer",
done: false
}
];

const nextState = produce(baseState, draftState => {
draftState[1].done = true
});
``````

## Resources:

This Presentation is based on examples and explanations from Functional Lite JavaScriptΒ by Kyle Simpson