Learn You a Functional JavaScript for Great Good! Mike Harris
Functions! Closures! Currying! Combinators! Multimethods
Frameworks
> require("underscore");! { [Function]! _: [Circular],! VERSION: '1.6.0',! …! map: [Function],! …! filter: [Function],! reject: [Function],! …! compose: [Function],! after: [Function],! …! }
> require("allong.es");! { es: ! {! …! flip: [Function: unary],! …! curry: [Function: unary],! map: [Function: binary],! mapWith: [Function: binary],! mapArgumentsWith: [Function: binary],! filter: [Function: binary],! filterWith: [Function: binary],! …! allong: [Circular] }
> require("bilby");! {! …! curry: [Function: curry],! flip: [Function: flip],! identity: [Function: identity],! constant: [Function: constant],! compose: [Function: compose],! …! lens: [Function: lens],! isLens: [Function],! objectLens: [Function: objectLens],! …! }
Functions
nothing function nothing(){};! ! nothing();! undefined
five function five(){return 5;};! ! five();! 5
make
 Five function makeFive(){! return function(){return 5;}! };! ! makeFive();! [Function]! var five = makeFive();! five();! 5
fAdd function five(){return 5;};! ! function fAdd(f, g){! return f() + g();! };! ! fAdd(five, five);! 10
Closures
Closure Function Environment
HelloMaker hello greet
function helloMaker(){! var greet = "Hello";! return function(){return greet;};! };! ! var hello = helloMaker();! hello();! ! 'Hello'
function helloMaker(){! var greet = "Hello";! return function(){return greet;};! };! ! var hello = helloMaker();! hello();! ! 'Hello' environment function
Counter get count
function counter(){! var count = 0;! return function(){return ++count;};! };! ! var ids = counter();! ! ids();! 1! ! ids();! 2
function counter(){! var count = 0;! return function(){return ++count;};! };! ! var ids = counter();! ! ids();! 1! ! ids();! 2 environment function
Currying
f(a, b, c, d) g(b, c, d) h(c, d) j(d)
f(a, b, c, d) Curry g(b, c, d) Curry h(c, d)Curry j(d)
ownAdd f(a, b, c) Curry g(b, c)Curry h(c)
var ownAdd = function(a){! return function(b){! return function(c){! return a + b + c;! }! }! };! ! ownAdd(1)(2)(3);! 6
var ownAdd = function(a){! return function(b){! return function(c){! return a + b + c;! }! }! };! ! ownAdd(1)(2)(3);! 6 ownAdd
add1 g(b, c) Curry h(c)
var ownAdd = function(a){! return function(b){! return function(c){! return a + b + c;! }! }! };! ! var add1 = ownAdd(1);! add1(2)(3);! 6
var ownAdd = function(a){! return function(b){! return function(c){! return a + b + c;! }! }! };! ! var add1 = ownAdd(1);! add1(2)(3);! 6 add1 a = 1
add3 h(c)
var ownAdd = function(a){! return function(b){! return function(c){! return a + b + c;! }! }! };! ! var add3 = ownAdd(1)(2);! add3(3);! 6
var ownAdd = function(a){! return function(b){! return function(c){! return a + b + c;! }! }! };! ! var add3 = ownAdd(1)(2);! add3(3);! 6 add3 a = 1 b = 2
Combinators Moses Schönfinkel
 and
 Haskell Curry
Bluebird B f g x = f (g x)
Compose B f g x = f (g x)
Compose Function Function Function
Compose Function Function Function
Square and Add 1 x + 1 x * x
var compose = require(“underscore").compose;! ! var sqAnd1 = compose(! function(x){return x+1;},! function(x){return x*x;}! );! ! sqAnd1(2);! 5
Guid sha1 str counter
var compose = require("underscore").compose,! sha1 = require("node-sha1"),! ! function counter(){! var count = 0;! return function(){return ++count;};! };! ! function str(s){! return s ? s.toString() : "";! };! ! var guid = compose(sha1, str, counter());! ! guid();! '356a192b7913b04c54574d18c28d46e6395428ab'! guid();! 'da4b9237bacccdf19c0760cab7aec4a8359010b0'
var! _ = require("underscore"),! compose = _.compose;
_.compose = function() {! var funcs = arguments;! return function() {! var args = arguments;! for (var i = funcs.length - 1; i >= 0; i--) {! args = [funcs[i].apply(this, args)];! }! return args[0];! };! };
Compose Function Function Function
_.compose = function() {! var funcs = arguments;! return function() {! var args = arguments;! for (var i = funcs.length - 1; i >= 0; i--) {! args = [funcs[i].apply(this, args)];! }! return args[0];! };! };
Cardinal C f x y = f y x
Flip / With C f x y = f y x
Flip C f x y = f y x
flip b a
var flip = require("bilby").flip;! ! function cat(s, t){return s + t;};! ! cat("Hello ", "Mike ");! 'Hello Mike '! ! flip(cat)("Hello ")("Mike ");! 'Mike Hello '
var flip = require("bilby").flip;! ! function cat(s, t){return s + t;};! ! var post = flip(cat);! ! var messageToMike = post("Mike ");! ! messageToMike("Hello ");! 'Hello Mike '! ! messageToMike("Bye ");! 'Bye Mike '
var! bilby = require("bilby"),! flip = bilby.flip;
function flip(f) {! return function(a) {! return function(b) {! return f(b, a);! };! };! }
flip b a
function flip(f) {! return function(a) {! return function(b) {! return f(b, a);! };! };! }
With C f x y = f y x
Filter _.filter = _.select = function(obj, predicate, context) { var results = []; if (obj == null) return results; if (nativeFilter && obj.filter === nativeFilter) return obj.filter(predicate, context); each(obj, function(value, index, list) { if (predicate.call(context, value, index, list)) results.push(value); }); return results; };
filter array function
filter 1, 2, 3 isEven
var filter = require("underscore").filter;! ! function isEven(x){return x%2 === 0;};! isEven(2);! true! ! filter([1, 2, 3], isEven);! [ 2 ]! ! [1, 2, 3].filter(isEven);! [ 2 ]
var! _ = require("underscore"),! filter = _.filter;
_.filter = _.select = function(obj, predicate, context) {! var results = [];! if (obj == null) return results;! if (nativeFilter && obj.filter === nativeFilter) ! return obj.filter(predicate, context);! each(obj, function(value, index, list) {! if (predicate.call(context, value, index, list))! results.push(value);! });! return results;! };
filter array function
_.filter = _.select = function(obj, predicate, context) {! var results = [];! if (obj == null) return results;! if (nativeFilter && obj.filter === nativeFilter) ! return obj.filter(predicate, context);! each(obj, function(value, index, list) {! if (predicate.call(context, value, index, list))! results.push(value);! });! return results;! };
FilterWith var filter = binary( function filter (list, fn) { fn = functionalize(fn); return __filter.call(list, fn); }); var filterWith = flip(filter);
filterWith arrayfunction
filterWith 1, 2, 3isEven
var filterWith = require("allong.es").allong.es.filterWith;! ! function isEven(x){return x%2 === 0;};! var evenOnly = filterWith(isEven);! ! evenOnly([1, 2, 3]);! [ 2 ]! ! evenOnly([42, 113]);! [ 42 ]! ! evenOnly([2, 1232, 131, 2, 13]);! [ 2, 1232, 2 ]
var! allonges = require("allong.es").allong.es,! filterWith = allonges.filterWith
var filter = binary( function filter (list, fn) {! fn = functionalize(fn);! ! return __filter.call(list, fn);! });! ! var filterWith = flip(filter);
filterWith arrayfunction
var filter = binary( function filter (list, fn) {! fn = functionalize(fn);! ! return __filter.call(list, fn);! });! ! var filterWith = flip(filter);
Multimethods
Environment Method Predicate FunctionName
Environment Method Predicate FunctionName (name, predicate) name predicate function
var! bilby = require("bilby"),! environment = bilby.environment;
animals voice isA sayspeak
var environment = require("bilby").environment;! var animals = environment();! ! function voice(type, sound){! return ["The", type, "says", sound].join(" ");! };! ! function isA(thing){! return function(obj){! return obj.type == thing;! };! };! ! function say(sound){! return function(obj){! console.log(voice(obj.type, sound));! };! };
animals voice isA sayspeak
var environment = require("bilby").environment;! var animals = environment();! ! function voice(type, sound){! return ["The", type, "says", sound].join(" ");! };! ! function isA(thing){! return function(obj){! return obj.type == thing;! };! };! ! function say(sound){! return function(obj){! console.log(voice(obj.type, sound));! };! }; method environment predicate function
Animals voice cat meowspeak (speak, cat) speak cat meow
var animals = animals.method(! “speak",! isA(“cat"),! say("meow"));! var animals = animals.method(! “speak",! isA(“dog"),! say("woof"));! ! animals.speak({type: "dog"});! The dog says woof! ! animals.speak({type: "cat"});! The cat says meow
Animals voice cat meowspeak (speak, cat) speak cat meow
var animals = animals.method(! “speak",! isA(“cat"),! say("meow"));! var animals = animals.method(! “speak",! isA(“dog"),! say("woof"));! ! animals.speak({type: "dog"});! The dog says woof! ! animals.speak({type: "cat"});! The cat says meow name predicate function environment
“What does the fox say?”
var animals = animals.method(! "speak",! isA("fox"),! say(“Wa-pa-pa-pa-pa-pa-pow!")! );! ! animals.speak({type:"fox"});! The fox says Wa-pa-pa-pa-pa-pa-pow!
Dante, The Divine Comedy
 Canto 24 A longer ladder yet remains to scale.
Functional JavaScript Michael Fogus
JavaScript Allonge Reginald Braithwaite
Learn You a Haskell for Great Good! Miran Lipovača
The Joy of Clojure Michael Fogus$ Chris Houser
Nietzsche, Human, All Too Human
 Aphorism 633 Now we will no longer concede so easily that anyone has the truth.
Thank you.
Mike Harris
 @MikeMKH! http://comp-phil.blogspot.com/

Learn You a Functional JavaScript for Great Good