Download - Millionways
var sum = function(xs) {
if(xs.length === 0) return 0;
return first(xs) + sum(rest(xs));
}
Base Case
ActionRecursion
var reverse = function(xs) {
if(xs.length === 0) return [];
return reverse(rest(xs)).concat(first(xs));
}
var reverse = function(xs) {
if(xs.length === 0) return [];
return reverse(rest(xs)).concat(first(xs));
}
Base Case
ActionRecursion
var sum = function(xs) {
if(xs.length === 0) return 0;
return first(xs) + sum(rest(xs));
}
sum([1,2,3])
// 1 + sum([2,3])
// 1 + (2 + sum([3]))
// 1 + (2 + (3 + sum([])))
// 1 + (2 + (3 + 0))
// 1 + (2 + 3)
// 1 + 5
//=> 6
var sum = function(xs) {
if(xs.length === 0) return 0;
return first(xs) + sum(rest(xs));
}
RangeError: Maximum call stack size exceeded
var sum = function(xs) {
if(xs.length === 0) return 0;
return first(xs) + sum(rest(xs));
}
var sum = function(list) {
function go(acc, xs) {
if(xs.length === 0) return acc;
return go(acc+first(xs), rest(xs));
}
return go(0, list)
}
var sum = function(xs) {
if(xs.length === 0) return 0;
return first(xs) + sum(rest(xs));
}
var sum = function(list) {
function go(acc, xs) {
if(xs.length === 0) return acc;
return go(acc+first(xs), rest(xs));
}
return go(0, list)
}
var reduce = function(f, acc, xs) {
if(xs.length === 0) return acc;
return reduce(f, f(acc, first(xs)), rest(xs));
}
var reduce = function(f, acc, xs) {
if(xs.length === 0) return acc;
return reduce(f, f(acc, first(xs)), rest(xs));
}
var sum = function(xs){
return reduce((acc, x) => x + acc, 0, xs)
}
var reverse = function(xs) {
return reduce((acc, x) => [x].concat(acc), [], xs)
}
var map = function(f, xs) {
return reduce((acc, x) => acc.concat(f(x)), [], xs)
}
var filter = function(f, xs) {
return reduce((acc, x) => f(x) ? acc.concat(x) : acc, [], xs)
}
var para = function(f, acc, xs) {
if(xs.length === 0) return acc;
return para(f, f(acc, first(xs), xs), rest(xs));
}
var para = function(f, acc, xs) {
if(xs.length === 0) return acc;
return para(f, f(acc, first(xs), xs), rest(xs));
}
var unfold = function(f, seed) {
function go(f, seed, acc) {
var res = f(seed);
return res ? go(f, res[1], acc.concat([res[0]])) : acc;
}
return go(f, seed, [])
}
unfold(x => if(x < 26) [String.fromCharCode(x+65), x+1], 0);
//=> [A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z]
var range = function(i, count) {
return unfold(x => if(x <= count) [x, x+1], i);
}
range(5,10)
//=> [ 5, 6, 7, 8, 9, 10 ]
var tree = Node(Node(Leaf(2), 1, Leaf(3)), 0, Leaf(4))
fold((acc, x) => acc + x, 0, tree)
//=> 10
var clicks = $("#red-button").asEventStream("click")
fold((acc, el) => acc.append(el.id), $("#clicklog"), clicks)
//=> <div id=“clicklog”/>
var us = {
“391": "keith@suburban",
“52": “[email protected]"
}
fold((acc, addr) => acc.cc(addr), Email.create(), us)
var Nil = {}
var _Cons = function(h, tl) {
this.head = h;
this.tail = tl;
};
var Cons = function(h, tl) { return new _Cons(h, tl) }
var lst = Cons(3, Cons(4, Cons(5, Nil)));
var Empty = {}
var _Leaf = function(x) { this.x = x; }
var Leaf = function(x) { return new _Leaf(x) }
var _Node = function(l, x, r) {
this.left = l;
this.x = x;
this.right = r;
}
var Node = function(l, x, r) { return new _Node(l, x, r) }
var map = function(f, xs) {
return reduce((acc, x) => concat(acc, f(x)), [], xs)
}
Accumulation
Transformation Iteration
var mapper = function(f) {
return (acc, x) => concat(acc, f(x))
}
reduce(mapper(x => x + 1), [], [1,2,3])
//=> [2,3,4]
var mapper = function(f) {
return (acc, x) => concat(acc, f(x))
}
reduce(mapper(x => x + 1), [], [1,2,3])
//=> [2,3,4]
var mapper = function(f, cnct) {
return (acc, x) => cnct(acc, f(x))
}
reduce(mapper(x => x + 1, concat), [], [1,2,3])
//=> [2,3,4]
var mapper = function(f, cnct) {
return (acc, x) => cnct(acc, f(x))
}
reduce(mapper(x => x + 1, concat), [], [1,2,3])
//=> [2,3,4]
var filterer = function(f, cnct) {
return (acc, x) => f(x) ? cnct(acc, x) : acc
}
reduce(filterer(x => x > 1, concat), [], [1,2,3])
//=> [2,3]
var filterer = function(f, cnct) {
return (acc, x) => f(x) ? cnct(acc, x) : acc
}
reduce(filterer(x => x > 1, concat), [], [1,2,3])
//=> [2,3]
var filterer = function(f, cnct) {
return (acc, x) => f(x) ? cnct(acc, x) : acc
}
reduce(filterer(x => x > 1, concat), [], [1,2,3])
//=> [2,3]
reduce(filterer(x => x > 1,
mapper(x => x + 1, append)),
Nil, Cons(1, Cons(2, Cons(3, Nil))))
//=> [3,4]
reduce(filterer(x => x > 1,
mapper(x => x + 1, append)),
Nil, Cons(1, Cons(2, Cons(3, Nil))))
//=> [3,4]
reduce(filterer(x => x > 1,
mapper(x => x + 1, insert)),
Empty, Node(Node(Leaf(2), 1, Leaf(3)), 0, Leaf(4)))
//=> [3,4]
reduce(filterer(x => x > 1,
mapper(x => x + 1, insert)),
Empty, Node(Node(Leaf(2), 1, Leaf(3)), 0, Leaf(4)))
//=> [3,4]
// left identity
concat([], xs) == xs
// right identity
concat(xs, []) == xs
// associativity
concat(concat(xs, ys), zs) == concat(xs, concat(ys, zs))
_Sum.prototype.concat = function(y){
return Sum(this.val + y.val)
}
_Sum.prototype.empty = function(){ return Sum(0) }
var sum = function(xs) {
return reduce((acc, x) => acc + x, 0, xs)
}
_Sum.prototype.concat = function(y){
return Sum(this.val + y.val)
}
_Sum.prototype.empty = function(){ return Sum(0) }
var sum = function(xs) {
return reduce((acc, x) => acc + x, 0, xs)
}
fold([Sum(1), Sum(2), Sum(3), Sum(4)])
//=> Sum(10)
_Sum.prototype.concat = function(y){
return Sum(this.val + y.val)
}
_Sum.prototype.empty = function(){ return Sum(0) }
fold([Product(1),Product(2),Product(3),Product(4)])
//=> Product(24)
_Product.prototype.concat = function(y){
return Product(this.val * y.val)
}
_Product.prototype.empty = function(){ return Product(1) }
fold([Max(11),Max(16),Max(3),Max(9)])
//=> Max(16)
_Max.prototype.concat = function(y){
return Max(this.val > y.val ? this.val : y.val)
}
_Max.prototype.empty = function(){ return Max(-Infinity) }
_All.prototype.concat = function(y){
return Any(this.val && y.val)
}
_All.prototype.empty = function(){ return All(true) }
fold([All(false), All(false), All(true), All(false)])
//=> All(false)
_Any.prototype.concat = function(y){
return Any(this.val || y.val)
}
_Any.prototype.empty = function(){ return Any(false) }
fold([Any(false), Any(false), Any(true), Any(false)])
//=> Any(true)
_Any.prototype.concat = function(y){
return Any(this.val || y.val)
}
_Any.prototype.empty = function(){ return Any(false) }
fold([Any(false), Any(false), Any(true), Any(false)])
//=> Any(true)
var foldMap = function(f,xs) {
return compose(fold, map(f))(xs);
}
var sum = function(xs){ return foldMap(Sum, xs).val }
var max = function(xs){ return foldMap(Max, xs).val }
var any = function(xs){ return foldMap(Any, xs).val }
var tree = Node(Node(Leaf(2), 1, Leaf(3)), 2, Leaf(4))
sum(tree)
//=> 12
product(tree)
//=> 38
max(tree)
//=> 4
Nil.map = function(f) { return Nil; }
_Cons.prototype.map = function(f) {
return Cons(this.head, f(this.tail))
}
var sum = function(x) {
return (x === Nil) ? 0 : x.head + x.tail
}
var lst = Cons(2, Cons(3, Cons(4, Nil)));
cata(sum, lst);
//=> 9
var sum = function(x) {
return (x === Nil) ? 0 : x.head + x.tail
}
var lst = Cons(2, Cons(3, Cons(4, Nil)));
cata(sum, lst);
//=> 9
Algebra
var sum = function(x) {
return (x === Nil) ? 0 : x.head + x.tail
}
var lst = Cons(2, Cons(3, Cons(4, Nil)));
cata(sum, lst);
// Nil
// Cons(4, 0)
// Cons(3, 4)
// Cons(2, 7)
//=> 9
map(x => x + 1, Cons(2, Cons(3, Cons(4, Nil))))
//=> Cons(3, Cons(4, Cons(5, Nil)))
var map = function(f, xs) {
return cata(x => (x == Nil) ? Nil : Cons(f(x.head), x.tail), xs)
}
Empty.map = function(f) { return Empty }
_Leaf.prototype.map = function(f) {
return Leaf(this.x)
}
_Node.prototype.map = function(f) {
return Node(f(this.left), this.x, f(this.right))
}
cata(t =>
switch (t.constructor) {
case _Node: return t.left + t.x + t.right;
case _Leaf: return t.x;
default: 0;
}, tr)
//=> 10
var tr = Node(Node(Leaf(2), 1, Leaf(3)), 0, Leaf(4))
var arrToList = function(xs) {
return xs.length === 0 ? Nil : Cons(first(xs), rest(xs))
}
ana(arrToList, [1,2,3,4,5])
//=> Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Nil)))))
CoAlgebra
var arrToList = function(xs) {
return xs.length === 0 ? Nil : Cons(first(xs), rest(xs))
}
ana(arrToList, [1,2,3,4,5])
//=> Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Nil)))))
var arrToList = function(xs) {
return xs.length === 0 ? Nil : Cons(first(xs), rest(xs))
}
ana(arrToList, [1,2,3,4,5])
//=> Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Nil)))))
var makeAlphabet = function(x) {
if(x > 25) return Nil;
return Cons(String.fromCharCode(x+65), x+1);
}
ana(makeAlphabet, 0)
//=> Cons(A, Cons(B, Cons(C, Cons(D, Cons(E, Cons(F, Cons(G, Cons(H, Cons(I, Cons(J, Cons(K, Cons(L, Cons(M, Cons(N, Cons(O,
var range = function(acc, count) {
return ana(x => (x >= count) ? Nil : Cons(x, x+1), acc)
}
range(2, 10)
//=> Cons(2, Cons(3, Cons(4, Cons(5, Cons(6, Cons(7, Cons(8,
Cons(9, Nil))))))))
var _Const = function(val) { this.val = val }
var Const = function(x) { return new _Const(x) }
var _Add = function(x, y) {
this.x = x;
this.y = y;
}
var Add = function(x, y) { return new _Add(x, y) }
var _Mul = function(x, y) {
this.x = x
this.y = y
}
var Mul = function(x, y) { return new _Mul(x, y) }
_Const.prototype.map = function(f) { return this }
_Add.prototype.map = function(f) {
return Add(f(this.x), f(this.y))
}
_Mul.prototype.map = function(f) {
return Mul(f(this.x), f(this.y))
}
var interpret = function(a) {
switch(a.constructor) {
case _Mul: return a.x * a.y;
case _Add: return a.x + a.y;
case _Const: return a.val;
}
}
var program = Mul(Add(Const(2), Const(3)), Const(4))
cata(interpret, program);
//=> 20
var _Concat = function(v, next) {
this.val = v;
this.next = next;
}
var Concat = function(v, x){ return new _Concat(v, x) }
var _Replace = function(v, x, next) {
this.val = v;
this.x = x;
this.next = next;
}
var Replace = function(v, x, nt){ return new _Replace(v, x, nt) }
var _Input = function(v) { this.val = v }
var Input = function(v){ return new _Input(v) }
_Concat.prototype.map = function(f) {
return Concat(this.val, f(this.next))
}
_Replace.prototype.map = function(f) {
return Replace(this.val, this.x, f(this.next))
}
_Input.prototype.map = function(f) {
return Input(this.val)
}
var interpret = function(t) {
switch (t.constructor) {
case _Concat: return t.next.concat(t.val);
case _Replace: return t.next.replace(t.val, t.x);
case _Input: return t.val;
}
}
var prog = Concat("world", Replace("h", "m", Input(“hello")))
cata(interpret, prog)
//=> melloworld
var interpret1 = function(t) {
switch (t.constructor) {
case _Concat:
return "concatting “+t.val+" after "+t.next;
case _Replace:
return "replacing "+t.val+" with "+t.x+" on "+t.next;
case _Input:
return t.val;
}
}
var prog = Concat("world", Replace("h", "m", Input(“hello")))
cata(interpret1, prog)
//=> concatting world after replacing h with m on hello
THanks!
@drbooleanhttps://github.com/DrBoolean/RecursionTalk