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