

No ifs…alternatives to statement branching in JavaScript - meowzero
http://javascriptweblog.wordpress.com/2010/07/26/no-more-ifs-alternatives-to-statement-branching-in-javascript/

======
jules
I thought this was going to be about booleans from nothing at all:

    
    
        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.

~~~
freyrs3
You really can build everything out of anonymous functions, including all of
arithmetic:

    
    
        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.

~~~
jules
The only problem then is, how do you do pred the inverse of succ? ;)

~~~
mathgladiator
The same way you build the integers. Built it out of pairs.

a --> (a,0)

-a --> (0,a)

succ((a,0)) = (a+1,0)

pred((a,0)) = (a,0+1)

~~~
mathgladiator
via something like: <http://news.ycombinator.com/item?id=2030649>

------
johnthedebs
It's worth noting that these techniques also work in other languages - I've
been doing this more and more often in the Python code I write.

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.

------
donpdonp
An alternative to 'if' that I like but havent seriously used before is
<expression>.true? {block}. an example in ruby:

(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

~~~
danudey
I'm only familiar with Ruby syntax, and not 100% fluent in it, but it seems to
me like this kind of shortcut could make your code much less readable for not
a whole lot of gain. I'm curious what the major benefit is over doing it 'the
old fashioned way'.

------
jvoorhis
This seems to boil down to a preference for expressions over statements. It's
easier to reason about the meaning of a value than a listing of commands, and
more insightful to recombine subexpressions to make values than to recombine
statements to get side-effects and void.

------
telemachos
A previous round of comments:

<http://news.ycombinator.com/item?id=1581830>

