In which I expound on things that are interesting to me.
Garrett Dawson
@killtheliterate
It is a programming style that "...produces abstraction through clever ways of combining functions" [1]
How is abstraction produced using this style of programming?
By Leveraging first class functions and higher-order functions
...also, by pretty much hating global state
First class functions are values, and can be used in every way that typical expressions can
Can be assigned to variables
var foo = function() {return 'hai'};
foo(); // "hai"
Can be returned by functions
var bar = function() {
return function() {return 'hai'};
};
bar(); // function () {return 'hai'}
Can be passed as arguments to other functions
var baz = function(func) {
return func();
};
baz(function() {return 'hai'}) // "hai"
Use functions as its parameters and/or return a function
var bar = function(func) {
return function() {
return func();
};
};
bar(function() {return 'hai'})() // "hai"
it's a style, not a syntax
How, functional JavaScript?
We know:
Stateful functions mutate state outside of their scope. FP avoids mutation.
var number = 1; // This is NOT functional programming
var increment = function() {
return number += 1;
};
increment(); // 2
increment(); // 3
increment(); // 4
* Stephen Young [2]
Stateless functions don't mutate state outside their scope
var number = 1;
var increment = function(n) {
return n + 1;
};
increment(number); // 2
increment(number); // 2
increment(number); // 2
* Stephen Young [2]
To understand recursion, you must understand recursion.
*Anonymous
Functions that call themselves
var loop = function(n) {
if (n > 9) {
console.log(n);
return;
} else {
console.log(n);
loop(n + 1);
}
};
loop(0);
* Stephen Young [2]
Applicative programming is a technique that allows a function to be applied to each element of a list
*Mary Simoni [3]
Array.prototype.map()
var squared = [1, 2, 3, 4, 5].map(function(el) {
return Math.pow(el, 2);
}); // [1, 4, 9, 16, 25]
Array.prototype.filter()
var even = [1, 2, 3, 4, 5].filter(function(el) {
return el % 2 === 0;
}); // [2, 4]
Array.prototype.reduce()
var sum = [1, 2, 3, 4, 5].reduce(function(memo, curr) {
return memo + curr;
}); // 15
A predicate determines whether or not something is true or false.
var isNull = function(obj) {
return obj === null;
};
isNull(null) // true
Closures are functions that refer to independent (free) variables... the function defined in the closure "remembers" the environment in which it was created.
*Person that wrote the MDN page[5]
function stringCount(string) {
return function(subString) {
return string.match(new RegExp(subString, 'g')).length;
};
}
var count = stringCount('sup sup sup');
count('sup'); // 3
Currying is the act of taking a function that takes more than one argument and converting it to an equivalent function taking one argument.
*Reginald Braithwaite [3]
var foo = function (x) {
return function (y) {
return function (z) {
return x + y + z;
}
}
}
var bar = foo(1) // partially applied function
bar(2)(3) // 6
It’s really that simple: Whenever you are chaining two or more functions together, you’re composing them
*Reginald Braithwaite [4]
var compose = function(a, b) {
return function (c) {
return a(b(c));
};
};
var addOne = function(number) { return number + 1 };
var double = function(number) { return number * 2 };
var addOneAndDouble = compose(double, addOne); // right to left
addOneAndDouble(2); // 6
(AKA Easy Mode)
var numbers = _.filter([1, 'foo', 3, 'bar', 5, 6], _.isNumber); // [1, 3, 5, 6]
var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) {
return num % 2 == 0;
}); // [2, 4, 6]
var evens = ramda.filter(function(num){ return num % 2 === 0; });
evens([1, 2, 3, 4, 5, 6]); // [2, 4, 6]
There is a lot to know about FP