malkomalko
4/11/2013 - 5:07 AM

list-out-of-lambda.js

var empty_list = function(selector) {
    return selector(undefined, undefined, true);
};

var prepend = function(el, list) {
    return function(selector) {
        return selector(el, list, false);
    };
};
var head = function(list) {
    return list(function(h, t, e) {
        return h;
    });
};
var tail = function(list) {
    return list(function(h, t, e) {
        return t;
    });
};

var is_empty = function(list) {
    return list(function(h, t, e) {
        return e;
    });
};

var not = function(x) {
    if (x) {
        return false;
    } else {
        return true;
    }
};
var and = function(a, b) {
    if (a) {
        if (b) {
            return true;
        } else {
            return false;
        }
    } else {
        return false;
    }
};
var or = function(a, b) {
    if (a) {
        return true;
    } else {
        if (b) {
            return true;
        } else {
            return false;
        }
    }
};

var map = function(fn, l) {
    if (is_empty(l)) {
        return empty_list;
    } else {
        return prepend(fn(head(l)), map(fn, tail(l)));
    }
};
var filter = function(fn, l) {
    if (is_empty(l)) {
        return empty_list;
    } else if (fn(head(l))) {
        return prepend(head(l), filter(fn, tail(l)));
    } else {
        return filter(fn, tail(l));
    }
};

var zero = empty_list;

var inc = function(n) {
    return prepend(empty_list, n);
};
var dec = function(n) {
    return tail(n);
};

var one = inc(zero);

var is_zero = function(n) {
    return is_empty(n);
};

var add = function(a, b) {
    if (is_zero(b)) {
        return a;
    } else {
        return add(inc(a), dec(b));
    }
};
var sub = function(a, b) {
    if (is_zero(b)) {
        return a;
    } else {
        return add(dec(a), dec(b));
    }
};
var mul = function(a, b) {
    if (is_zero(b)) {
        return zero;
    } else {
        return add(a, mul(a, dec(b)));
    }
};
var pow = function(a, b) {
    if (is_zero(b)) {
        return one;
    } else {
        return mul(a, pow(a, dec(b)));
    }
};

var is_equal = function(n, m) {
    if (and(is_zero(n), is_zero(m))) {
        return true;
    } else if (or(is_zero(n), is_zero(m))) {
        return false;
    } else {
        return is_equal(dec(n), dec(m));
    }
};
var less_than = function(a, b) {
    if (and(is_zero(a), is_zero(b))) {
        return false;
    } else if (is_zero(a)) {
        return true;
    } else if (is_zero(b)) {
        return false;
    } else {
        return less_than(dec(a), dec(b));
    }
};
var greater_than = function(a, b) {
    return less_than(b, a);
};

var div = function(a, b) {
    if (less_than(a, b)) {
        return zero;
    } else {
        return inc(div(sub(a, b), b));
    }
};
var rem = function(a, b) {
    if (less_than(a, b)) {
        return a;
    } else {
        return rem(sub(a, b), b);
    }
};

var nth = function(l, n) {
    if (is_zero(n)) {
        return head(l);
    } else {
        return nth(tail(l), dec(n));
    }
};
var drop = function(l, n) {
    if (is_zero(n)) {
        return l;
    } else {
        return drop(tail(l), dec(n));
    }
};
var take = function(l, n) {
    if (is_zero(n)) {
        return empty_list;
    } else {
        return prepend(head(l), take(tail(l), dec(n)));
    }
};
var slice = function(l, start, end) {
    return take(drop(l, start), sub(end, start));
};
var length = function(l) {
    if (is_empty(l)) {
        return zero;
    } else {
        return inc(length(tail(l)));
    }
};