The Shapeof
FunctionalProgramming
Saturday, October 5, 13
@fogushttp://www.fogus.me
http://github.com/documentcloud/underscore-contrib
Saturday, October 5, 13
@fogus
“FunctionalJavaScript”Lemonad
codd.js
Saturday, October 5, 13
Aprogram
written in anobject-oriented
style
Saturday, October 5, 13
Functional programming
for the MEOW!
Saturday, October 5, 13
Saturday, October 5, 13
Pattern 1 - Map(ish)var array = [0,1,2,3,4,5];var transformed = []; for (var i = 0; i < array.length; i++) { transformed.push(array[i] + 100);} transformed;//=> [100, 101, 102, 103, 104, 105]
Saturday, October 5, 13
Pattern 1 - Map(ish)
// Underscore _.map(array, function(n) { return n + 100;}); // Lemonad L.map(L.add(100), array);
Saturday, October 5, 13
Pattern 2 - Filter(ish)var array = [0,1,2,3,4,5];var keepers = []; for (var i = 0; i < array.length; i++) { if (array[i] % 2 === 0) { keepers.push(array[i]); }} keepers;//=> [101, 102, 103, 104, 105]
Saturday, October 5, 13
Pattern 2 - Filter(ish)// Underscore _.filter(array, function(n) { if (n % 2 === 0) { return true; } else { return false; }}); // Lemonad L.filter(L.isEven, array);
Saturday, October 5, 13
Pattern 3 - Reduce(ish)
var array = [0,1,2,3,4,5];var sum = 0; for (var i = 0; i < array.length; i++) { sum += array[i];} sum;//=> 15
Saturday, October 5, 13
Pattern 3 - Reduce(ish)
// Underscore _.reduce(array, function(acc, n) { return acc + n;}, 0); // Lemonad L.reduce(L.uncurry(L.add), 0, array);
Saturday, October 5, 13
APL
life←{↑1 ⍵∨.∧3 4=+/,¯1 0 1∘.⊖¯1 0 1∘.⌽⊂⍵}
0 1 0 0 1 0 0 1 0
0 1 0
0 1 0
0 1 0
Saturday, October 5, 13
Fun.js at a glance
• Simple data
• Many small functions
• Larger abstractions built via composition
• OO to supplement (no dogma)
Saturday, October 5, 13
Simple data
Saturday, October 5, 13
“
Saturday, October 5, 13
#
Saturday, October 5, 13
42
Saturday, October 5, 13
?
Saturday, October 5, 13
Saturday, October 5, 13
[ ]Saturday, October 5, 13
#
Saturday, October 5, 13
#
[1, 2, 3, 4, 5]
Saturday, October 5, 13
Saturday, October 5, 13
{ }Saturday, October 5, 13
#“
Saturday, October 5, 13
#“
{x: 0, y: 1}
Saturday, October 5, 13
{x: 0, y: 1}
#
Saturday, October 5, 13
Saturday, October 5, 13
*Saturday, October 5, 13
Small functions
Saturday, October 5, 13
Saturday, October 5, 13
λSaturday, October 5, 13
λSaturday, October 5, 13
λSaturday, October 5, 13
Disclaimer
Saturday, October 5, 13
#
Procedure
Saturday, October 5, 13
#
Procedure
Saturday, October 5, 13
function logNth(array, index) { console.log(array[index]);}
logNth([‘a’, ‘b’, ‘c’], 1);// (console) b
#
Saturday, October 5, 13
Purity
Saturday, October 5, 13
Ostrich Purity
Saturday, October 5, 13
Ostrich Purity
Saturday, October 5, 13
#
Function
Kinda importantSaturday, October 5, 13
function nth(array, index) { return array[index];}
nth([‘a’, ‘b’, ‘c’], 1);//=> ‘b’
#
Saturday, October 5, 13
Saturday, October 5, 13
Saturday, October 5, 13
Saturday, October 5, 13
id name age
555-55-5555 Moe 45
777-77-7777 Curly 47
0
1
Saturday, October 5, 13
var table = [
{id: ‘555-55-5555’, name: ‘Moe’, age: 45},
{id: ‘777-77-7777’, name: ‘Curly’, age: 47}
];
Saturday, October 5, 13
id name age
555-55-5555 Moe 45
777-77-7777 Curly 47
0
1
Saturday, October 5, 13
#“
Saturday, October 5, 13
function cell(table, col, row){ return table[row][col];}
cell(table, ‘name’, 0);//=> ‘Moe’
cell(table, ‘age’, 0);//=> 45
#“
Saturday, October 5, 13
Larger abstractions built via composition
Saturday, October 5, 13
LClojure, Haskell, ML, Joy, _
Saturday, October 5, 13
Currying, partial application, fixation, oh
my!
Saturday, October 5, 13
#“
Saturday, October 5, 13
#“
L.fix
Saturday, October 5, 13
#
L.fix(cell, L._, ‘name’, L._);
‘name’
Saturday, October 5, 13
#
L.fix(cell, L._, ‘name’, L._);
var getName = L.fix(cell, L._, ‘name’, L._);
getName(table, 0);//=> ‘Moe’
getName(table, 1);//=> ‘Curly’
‘name’
Saturday, October 5, 13
#“
L.rot
Saturday, October 5, 13
#
L.rot(cell);
“
Saturday, October 5, 13
#“
L.partial
Saturday, October 5, 13
L.partial(L.rot(cell), ‘name’);
#‘name’
Saturday, October 5, 13
L.partial(L.rot(cell), ‘name’);
var getName = L.partial(L.rot(cell), ‘name’);
getName(0, table);//=> ‘Moe’
getName(1, table);//=> ‘Curly’
#‘name’
Saturday, October 5, 13
L.rcurry
“
Codd.col(table, ‘name’);//=> [‘Moe’, ‘Curly’]
Saturday, October 5, 13
“
“
L.rcurry2(Codd.col);
Saturday, October 5, 13
“
L.rcurry2(Codd.col);
var valuesFor = L.rcurry2(Codd.col);var allNames = valuesFor(‘name’);
allNames(table);//=> [‘Moe’, ‘Curly’]
Saturday, October 5, 13
Compositions and Pipelines
Saturday, October 5, 13
How to countall of the values
in a column?
Saturday, October 5, 13
“function countValues(table, tag) { return L.len(Codd.col(table, tag));}
countValues(table, ‘name’);//=> 2
#
Saturday, October 5, 13
L.comp
return L.len(Codd.col(table, tag));
First thisThen thisSaturday, October 5, 13
“Codd.col
#L.len
Saturday, October 5, 13
“Codd.col
#L.len
Saturday, October 5, 13
“
var countValues = L.comp(L.len, Codd.col);
countValues(table, ‘name’);//=> 2
#
Saturday, October 5, 13
L.pipeline
L.pipeline(table, Codd.col(‘name’), L.len);//=> 2
First this Then thisSaturday, October 5, 13
codd.js (demo)Relational Algebra
Saturday, October 5, 13
Thanks
• The NationJS team
• O’Reilly
• Alan Dipert
• Paul Khuong
• The Underscore community
• The Clojure community
Saturday, October 5, 13