

Fun.js – Just a sketch - DanielRibeiro
http://blog.fogus.me/2013/06/06/fun-js-just-a-sketch/

======
thepicard
A lot of these examples are wrong...

    
    
        function double(n) { return 2*n; }
        map(double, [1,2,3])
        //=> [1, 4, 9]
    

should be => [2, 4, 6]

    
    
        function greaterThan(l, r) {
          return l > r;
        }
        greaterThan(5, 100);
        //=> true
    

should be => false

    
    
        maybeGT(5)(10000000);
        //=> false
    

Based on your earlier declaration of greaterThan this result is actually
correct. The curried application ordering is also correct and flip is
unneeded.

    
    
        schonfinkel(function(a1,a2) {return [a1,a2];})(1)(2);
        //=> [1, 2]
    

I would proofread the rest but I am about to be late for class! =O

Edit: since i'm going to complain I might as well say something nice as well.
I did like this article example correctness aside, and I hadn't seen that
implementation of pipeline before! Much awesome. =)

~~~
thepicard
Actually, I think the original intent regarding greater than was:

    
    
        greaterThan(100, 5);
        //=> true
    

That is, l is greater than r, and to then properly curry the arguments _do_
need to be flipped such that maybeGT(5) results in a function that returns
whether the argument is greater than 5.

~~~
fogus
Exactly right. We like to be able to do something like:

    
    
        var gtThreshold = gt(100);
    

And then:

    
    
        filter(gtThreshold, array);
    

This is nicely fluent I would say.

------
dhucerbin
Some questions from JS novice:

Why map isn't implemented:

    
    
        function map(fun, coll) {
          if (exists(coll)) return _map(fun)(coll);
          return _map(fun);
        }
    

Why use _arguments_ when you can name your parameter in declaration?

And why __ma_ p is defined in global scope? Shouldn't it be better defined
inside _map_ function? What are up/downsides in performance for this move?

------
dweinus
Sorry to nitpick, but I got hung up right at the beginning with his "truthy"
function.

It returns true on values such as NaN, zero, or an empty string. I don't think
I'm alone in considering those to be "falsy" values, for example:

<http://www.sitepoint.com/javascript-truthy-falsy/>

~~~
fogus
Technically the are JS falsey, but I choose not to treat them that way. I
rarely want to treat the result of a calculation as a boolean condition.
However, I often want to know if a calculation isNaN or isEmpty. Just because
something is falsey doesn't mean it should be treated that way universally.

~~~
dweinus
Right on, I get that, but truthy(NaN) and truthy(5) both return true, so you
still don't know if the calculation isNaN.

Btw, I should have said first: I love the article in general and it's great to
see these techniques becoming more mainstream in javascript. Thank you!

~~~
fogus
I would probably structure the problem like this:

    
    
        var ans = someCalculation(x,y);
        
        if (truthy(ans) && !isNaN(ans))
          //do something
        else
          //do something else
    

The point being I like to dispatch conditions on boolean results of certain
properties of my results rather than the result directly. It helps me to keep
my sanity.

Thanks for the kind words BTW. :-)

------
tomTheBom
Very interesting post but I'm having trouble with one thing. pipeline(5)
returns 5. When I try to follow that path, I get to this: reduce(function(l,r)
{ return r(l); }, seed, funs) with seed=5 and funs=[] (an empty array). How
does that reduction evaluate to 5? In other words, what is "r(l)" when l=5 and
r=the first member of an empty array?

~~~
fogus
In reduce the accumulator starts as the seed and is changed in the forEach for
each elem. Since there are so elems (funs) the accumulator never changes and
returns as the value of seed (5).

~~~
tomTheBom
Of course. Shoulda seen that. ;) forEach on an empty collection returns
immediately. Thanks.

------
dugmartin
Just a note - forEach doesn't work in IE8. I wonder at what point can we stop
caring about that?

~~~
gotofritz
there are shims - the MDN one works well, or you can download this library to
shim the whole of ES5
[https://github.com/kriskowal/es5-shim](https://github.com/kriskowal/es5-shim)
(other libraries are availble)

Focusing on modern browsers and shimming the old ones is the way to go, IMHO

------
raam86
What would you say are the skills required to fully understand this?

~~~
barefoot
Possibly not too high. Try using map, filter, and reduce on some example
problems and you'll pick it up fairly quickly. Project Euler makes for decent
fodder. When you've successfully managed to apply them then try rewriting the
functions (delete the implementation you are using - such as the library above
- and rewrite it from scratch).

~~~
innguest
I wouldn't recommend Project Euler - it's math-based and that would be a
roundabout way of learning anything else but math.

Here's my recommendation: [http://www.haskell.org/haskellwiki/H-99:_Ninety-
Nine_Haskell...](http://www.haskell.org/haskellwiki/H-99:_Ninety-
Nine_Haskell_Problems)

------
graup
Good read, nice intro into functional programming. Thanks!

