No ifs…alternatives to statement branching in JavaScript
javascriptweblog.wordpress.com
javascriptweblog.wordpress.com
true = function(x,y){ return x; }
false = function(x,y){ return y; }
ifelse = function(x,a,b){ x(a,b)(); }
not = function(x){ return x(false,true); }
and = function(x,y){ return x(y,false); }
or = function(x,y){ return x(true,y); }
bool = and(not(true),or(true,false))
ifelse(bool,
function(){ alert("true!") },
function(){ alert("false!") }
)
Amazing, isn't it?It gets better.
Pairs:
pair = function(x,y){ return function(f){ return f(x,y); } }
fst = function(p){ return p(function(x,y){ return x; }); }
snd = function(p){ return p(function(x,y){ return y; }); }
Unions: left = function(x){ return function(f,g){ return f(x); } }
right = function(x){ return function(f,g){ return g(x); } }
Pairs combined with unions make lists: cons = function(x,y){ return left(pair(x,y)); }
head = function(l){ return l(function(p){ return fst(p); }, function(n){ alert("Can't take head of nil"); }) }
tail = function(l){ return l(function(p){ return snd(p); }, function(n){ alert("Can't take tail of nil"); }) }
nil = right(false)
isnil = function(l){ return l(function(p){ return false; }, function(n){ return true; }) }
map = function(f,l){
return ifelse(isnil(l),
function(){ return nil; },
function(){ return cons(f(head(l)),map(f,tail(l))); })
}
filter = function(f,l){
return ifelse(isnil(l),
function(){ return nil; },
function(){
return ifelse(f(head(l)),
function(){ return cons(head(l),filter(f,tail(l))); },
function(){ return filter(f,tail(l)); })
});
}
Isn't it neat how you can build everything, including conditionals, booleans, pairs and lists from functions?Note that this code was not tested in any way, so it likely contains bugs.
zero = function(x,y){ return y; }
succ = function (f) { return function (x) {return f(n(f(x)));};}
one = succ(zero);
two = succ(one);
Look up lambda calculus if anyone is interested.a --> (a,0)
-a --> (0,a)
succ((a,0)) = (a+1,0)
pred((a,0)) = (a,0+1)
pair = λ x. λ y. λ z. x. y. z
Or if you are willing to let pred(0) = 0 then you can use: pred = λ x. λy. λ z. x . (λ i. λ j. j. i. y (λ k. z) (λ k. k)I just did a construction of the integers assuming either sets or arrays. I could equally have used your list definition.
http://pastie.org/1397123 and http://news.ycombinator.com/item?id=2030649
I've very tempted to combine your work with this and then go on to define rationals and then the reals. The reals would be very interesting since it would be a sequence that takes an epsilon and gets a rational number that is close enough. It's kind of crazy to think that all these real numbers are infinite cauchy sequences.
If I define a real as function(eps) { return some_rational; } then I could define it piece_wise and say function mult_real(a,b) { return function(eps) { return a(eps/2) * b(eps/2); } }
If you aren't used to it, it looks a bit unusual (of course) but it makes for much cleaner, and therefore more maintainable, code.
(3==3).true?{'Yes'} => "Yes"
(4==4).true?{'Yes'} => nil
using this implementation:
class Object def true? yield end end
class FalseClass def true? end end
class NilClass def true? end end