Skip to content

Instantly share code, notes, and snippets.

@fabioyamate
Last active August 29, 2015 14:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fabioyamate/7b1f5772031990f18553 to your computer and use it in GitHub Desktop.
Save fabioyamate/7b1f5772031990f18553 to your computer and use it in GitHub Desktop.
Lazy evaluation implemented in Javascript (well just because it has strict evalution)
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