Skip to content

Instantly share code, notes, and snippets.

@sjl
Created March 30, 2013 17:58
Show Gist options
  • Star 48 You must be signed in to star a gist
  • Fork 20 You must be signed in to fork a gist
  • Save sjl/5277681 to your computer and use it in GitHub Desktop.
Save sjl/5277681 to your computer and use it in GitHub Desktop.
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)));
}
};
@travellingprog
Copy link

Very cool article! I simplified the less_than function and tested it to make sure it still works properly: https://gist.github.com/travellingprog/5280282

@aerosol
Copy link

aerosol commented Apr 3, 2013

Nice introduction to functional abstractions, big up!

@anakryiko
Copy link

As I haven't found a way to comment on original article (http://stevelosh.com/blog/2013/03/list-out-of-lambda/), need to write here :)

  1. There is one error in tracing log comments, which can mislead someone, probably. Instead of

// map(square, [1, 2, 3])
// prepend(square(1), map(square, [1, 2, 3]))

should be

// map(square, [1, 2, 3])
// prepend(square(1), map(square, [2, 3]))

  1. It seems there is off by one error in slice function, except if end is exclusive (which I doubt, though).

var slice = function(l, start, end) {
return take(drop(l, start), inc(sub(end, start))); // inc(...) call added
};

@magicmanam
Copy link

It's awesome! Thanks for this article!

@lonkamikaze
Copy link

I really enjoyed the article, very inspiring!

I have a question and a suggestion:

Are all the redundant elses good/recommended style?

I would remove the redundant logic from the less_than function:

var less_than = function(a, b) {
    if (is_zero(b)) {
        return false;
    }
    if (is_zero(a)) {
        return true;
    }
    return less_than(dec(a), dec(b));
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment