Just twitted the slides @JSDude005
Ref: Why FP matters
Like everyone else
ref: Charles Scalfani: So you want to be a functional programmer
you know
function add(x, y){
return x + y;
}
add(1, 2); // output is 3
add(1, 2); // output still is 3
add(1, 2); // WILL ALWAYS output 3
function mouseOnLeftSide(mouseX) {
return mouseX < window.innerWidth / 2;
}
Few more... impure function
writeFile(fileName);
updateDatabaseTable(sqlCmd);
sendAjaxRequest(ajaxRequest);
openSocket(ipAddress);
When a function produces a side effect you have to know more than just its inputs and output
Make global variable local
const myFunc = function(y){
const x = 10;
return x + y;
}
console.log(myFunc(3)); //13
console.log(myFunc(3)); //13
Pass as parameter
const x = 10;
const myFunc = function(x, y){
return x + y;
}
console.log(myFunc(x, 3)); //13
console.log(myFunc(x, 3)); //13
Basic Concept-1
// function expression
const doubleIt = x => x * 2;
function greaterThan(n) {
return function(m) {
return m > n;
};
}
const greaterThan10 = greaterThan(10);
greaterThan10(11); //true
greaterThan10(7); //false
const greaterThan15 = greaterThan(15);
greaterThan15(11); //false
greaterThan15(21); //true
Basic Concept-2
Immutability creates simpler and safer code.
var x = 1;
x = x + 1;
“HOW THE HELL AM I SUPPOSED TO DO ANYTHING WITHOUT VARIABLES?!”
Just create a new variable
Loop needs variable
for, while, do while, etc.
var sum = 0;
for (var i = 1; i <= 10; ++i){
sum += i;
}
console.log(sum); // prints 55
“WHAT NO VARIABLES AND NOW NO LOOPS?! I HATE YOU!!!”
let tasks = ['write code', 'drink coffee', 'hide from manager'];
const lengths = tasks.map(word => word.length);
console.log(lengths); // [10, 12, 17]
const getLength = word => word.length;
tasks.map(getLength);
meals.map(getLength);
const doubleIt = x => x*2;
tasks.map(getLength).map(doubleIt);
const numbers = [1, 2, 3, 4];
let newNumbers = [];
for(let i = 0; i < numbers.length; i++) {
if(numbers[i] % 2 !== 0) {
newNumbers[i] = numbers[i] * 2;
}
}
console.log(newNumbers); // [2, 6]
const numbers = [1, 2, 3, 4];
const odd = n => n % 2;
const doubleIt = x => x * 2;
const newNumbers = numbers.filter(odd).map(doubleIt);
Ref: map, filter, reduce
Basic Concept-3
Who was in the image "Fully Lost?"
Used in Functional Programming
f(x) = 2x + 3
f(5) = ?
f(5) = 2 * 5 + 3
= 10 + 3
= 13
g(x) = x 2 + 1
g(2) = ?
g(2) = 2 * 2 + 1
= 4 + 1
= 5
What is the value of f(g(x)) or f(g(2))?
f(g(2)) = f(5)
= 2 * 5 + 3
= 10 + 3
= 13
g(x) inside f(x)...inside executes first
const mult5 = x => x * 5;
const add10 = x => x + 10;
const mult5AfterAdd10 = x => mult5(add10(x));
var compose = function(f, g) {
return function(x) {
return f(g(x));
};
};
const mult5 = x => x * 5;
const add10 = x => x + 10;
const mult5AfterAdd10 = compose(mult5, add10);
mult5AfterAdd10(5); //75
executes right to left
Direction matters
ref: Coding by composing
Ref: Haskell Brooks Curry
const sum3 = (x, y, z) => x + y + z;
sum3(1,2,3); //6
function currySum3(x){
return function (y){
return function (z){
return x + y + z;
}
}
}
const currySum3 = x => y => z => x + y + z;
currySum3(1)(2)(3); //= 6
A Curried Function is a function that only takes a single parameter at a time.
Ref: Why Curry Helps and Curry JS
const modulo = divisor => dividend => dividend % divisor;
modulo (3)(9); //0
const isOdd = modulo(2);
isOdd(6); //0
isOdd(5); //1
const f = a => b => c => d => a + b + c + d
f(1)(2)(3)(4); // returns 10
const f = R.curry((a, b, c, d) => a + b + c + d);
f(1, 2, 3, 4); // returns 10
f(1, 2)(3, 4); // also returns 10
f(1)(2)(3, 4); // also returns 10
Ref: Ramada JS
You use point free: to focus on how rather than what
Ref: Think point free
const toUpperCase = str => str.toUpperCase();
const head = str => str[0];
const compose = (f, g) => x => f(g(x));
//not point free because we mention the data: name
const initials = function(name) {
return name.split(' ').map(compose(toUpperCase,head)).join('. ');
};
initials("that js dude");
// 'T. J. D.'
//point free
const initials = compose(join('. '),
map(compose(toUpperCase, head)), split(' '));
Ref this and this as well or this
//Both f() and g() are in tail position
const a = x => x ? f() : g();
// g() is in a tail position
const a = () => f() || g();
const a = () => f() && g();
function fib(n) {
if (n <= 1){
return n;
} else {
return fib(n-1) + fib(n - 2);
}
}
function fibIterRecursive(n, a, b){
if (n === 0) {
return b;
} else {
return fibIterRecursive(n-1, a + b, a);
}
};
function fib(n){
return fibIterRecursive(n, 1, 0);
}
find all wiki that mention "nosql" in the text
grep -l 'nosql' wiki
grep -l 'nosql' wiki/* | xargs wc -w
grep -l 'nosql' wiki/* | xargs wc -w | sort -nr
grep -l 'nosql' wiki/* | xargs wc -w | sort -nr | head -4 | tail -3
const addOne = x => x + 1;
const square = x => x * x;
const minusTwo = x => x - 2;
// Not reusable
minusTwo(square(addOne(10)));
minusTwo(square(addOne(20)));
const someFormula = new Pipeline([ addOne, square, minusTwo ]);
someFormula.process(10);
someFormula.process(20)
// alternative approach
const someFormula = (new Pipeline()).pipe(addOne)
.pipe(square)
.pipe(minusTwo);
Ref: pipeline JS
const doubleSay = str => str + ", " + str;
const capitalize = str => str[0].toUpperCase() + str.substring(1);
const exclaim = str => str + '!';
let result = exclaim(capitalize(doubleSay("hello")));
let result = "hello" |> doubleSay |> capitalize |> exclaim;
//Hello, hello!
ref: JS pipeline proposal
While cooking curry...how many people were adding spices?
In theory, there is no difference between theory and practice. But, in practice, there is.
Ref: Category Theory
For any group of connected objects, a -> b -> c, there must be a composition which goes directly from a -> c
A functor is a container of type a that, when subjected to a function that maps from a→b, yields a container of type b.
ref: what is functor
A functor supplies a box with zero or more things inside, and a mapping interface.
const functor = [1, 2, 3];
functor.map(x => x); // [1, 2, 3]
functor.map(x => f(g(x))) ≡ functor.map(g).map(f)
const Container = x => ({
map:(f) => Container(f(x)),
toString(){return `Container(${x})`}
});
const inContainer = Container(5);
const mapped = inContainer.map(x => x*2)
mapped.toString(); //Container(10)
const transformValue = x => Container(x)
.map(x => x*2)
.map(x => x*3)
.map(x => x+46)
.map(x => String.fromCharCode(x))
Combine multiple functor into one functor
Ref: applicatives
var wrapped2 = [2];
var wrapped3 = [3];
//Won't work ! The values are wrapped.
add(wrapped2, wrapped3);
Ref: applicatives
The moment you understand what is monads, is the moment you loose the ability to explain it to someone else.
Functors apply a function to a wrapped value
Applicatives apply a wrapped function to a wrapped value
Monads apply a function that returns a wrapped value to a wrapped value
const half = x => (x%2 === 0) ? [x/2] : [];
Array.prototype.flatMap = function(lambda) {
return [].concat.apply([], this.map(lambda));
};
[3].flatMap(half); //[]
[4].flatMap(half); //[2]
[1,2,3,4,5,6,7,8].flatMap(half); //[1, 2, 3, 4]
Simple way: Monad is the container that Applies flatMap
Ref: monad in JS
Dog
.bark()
Cat
.meow()
Dog
.poop()
.bark()
Cat
.poop()
.meow()
Animal
.poop()
Dog
.bark()
Cat
.meow()
CleaningRobot
.drive()
.clean()
Animal
.poop()
Dog
.bark()
Cat
.meow()
MurderRobot
.drive()
.kill()
CleaningRobot
.drive()
.clean()
Animal
.poop()
Dog
.bark()
Cat
.meow()
Robot
.drive()
MurderRobot
.kill()
CleaningRobot
.clean()
Animal
.poop()
Dog
.bark()
Cat
.meow()
Robot
.drive()
MurderRobot
.kill()
CleaningRobot
.clean()
Animal
.poop()
Dog
.bark()
Cat
.meow()
Higher level object???
GameObject
.bark()
Robot
.drive()
MurderRobot
.kill()
CleaningRobot
.clean()
MurderRobotDog
Animal
.poop()
Dog
.bark()
Cat
.meow()
Robot
.drive()
MurderRobot
.kill()
CleaningRobot
.clean()
MurderRobotDog
.bark()
dog = pooper + barker
cat = pooper + meower
cleaningRobot = driver + cleaner
murderRobot = driver + killer
murderRobotDog = murderRobot + dog
killerDog = dog + killer
Write pure functionas much as possible