Last active
August 29, 2015 14:05
-
-
Save fabioyamate/7b1f5772031990f18553 to your computer and use it in GitHub Desktop.
Lazy evaluation implemented in Javascript (well just because it has strict evalution)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function empty_list() { | |
return null; | |
} | |
// concat :: [[a]] -> [a] | |
function concat(xs) { | |
return foldr(append, empty_list, xs); | |
} | |
// foldr :: (a -> b -> b) -> b -> [a] -> b | |
function foldr(f, z, xs) { | |
if (xs == empty_list) { | |
return z; | |
} else { | |
return f(car(xs), foldr(f, z, cdr(xs))); | |
} | |
} | |
// (++) :: [a] -> [a] -> [a] | |
function append(xs, ys) { | |
if (xs == empty_list) { | |
return ys; | |
} else { | |
return cons(function() { | |
return car(xs); | |
}, function() { | |
return append(cdr(xs), ys); | |
}); | |
} | |
} | |
var head = car; | |
var tail = cdr; | |
function tail(list) { | |
return cdr(list); | |
} | |
function map(f, xs) { | |
if (xs == empty_list) { | |
return empty_list; | |
} else { | |
return cons(function() { | |
return f(car(xs)); | |
}, function() { | |
return map(f, cdr(xs)); | |
}); | |
} | |
} | |
function cons(x, y) { | |
return function _cons(m) { | |
return m(x, y); | |
}; | |
} | |
function fst(x) { | |
return apply(x); | |
} | |
function snd(_, y) { | |
return apply(y); | |
} | |
function car(z) { | |
return z(fst); | |
} | |
function cdr(z) { | |
return z(snd); | |
} | |
function apply(expr) { | |
if (typeof expr === 'function') { | |
if (expr.name == "_cons") { | |
// the expr is a list (current a workaround) | |
// probably apply should be called as eval | |
return expr; | |
} else { | |
return expr(); | |
} | |
} else { | |
return expr; | |
} | |
} | |
function take(n, xs) { | |
if (n === 0) { | |
return empty_list; | |
} else if (xs === empty_list) { | |
return empty_list; | |
} else { | |
return cons(function() { | |
return car(xs); | |
}, function() { | |
return take(n - 1, cdr(xs)); | |
}); | |
} | |
} | |
function drop(n, xs) { | |
if (n === 0) { | |
return xs; | |
} else if (xs === empty_list) { | |
return empty_list; | |
} else { | |
return drop(n - 1, cdr(xs)); | |
} | |
} | |
function list() { | |
var args = Array.prototype.slice.call(arguments); | |
return args.reduceRight(function(acc, n) { | |
return cons(function() { return apply(n); }, function() { return acc }); | |
}, empty_list); | |
} | |
function doAll(f, list) { | |
if (list !== empty_list) { | |
f(car(list)); | |
doAll(f, cdr(list)); | |
} | |
} | |
function one() { | |
console.log('called 1'); | |
return 1; | |
} | |
function two() { | |
console.log('called 2'); | |
return 2; | |
} | |
function three() { | |
console.log('called 3'); | |
return 3; | |
} | |
function four() { | |
console.log('called 4'); | |
return 4; | |
} | |
l = concat(list(list(one), list(two))); | |
ll = list(three, four); | |
lll = append(l, ll); | |
function double(x) { return x * 2; } | |
function log(x) { console.log(x); } | |
function sum(a, b) { return a + b }; | |
//doAll(log, concat(list(list(one), list(two)))); | |
//console.log(foldr(sum, 0, list(1,2,3,4))); | |
//doAll(log, l); | |
doAll(log, take(3, map(double, lll))); | |
// called 1 | |
// 2 | |
// called 2 | |
// 4 | |
// called 3 | |
// 6 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment