read


read
or learn more

Fun.js – Functional JavaScript

May 29, 2013

I’ve written a book entitled Functional JavaScript due out in print sometime in June 2013. In the book I introduce and explore various techniques for writing code in a functional style using the Underscore library. As much as I would have loved to delve into the ecosystem of functional JS libraries, I didn’t want to distract from the core functional topics in the book.1 Therefore, I present a series to explore a few of my favorite functional JavaScript libraries2 focusing primarily on the feature(s) that make them interesting, innovative or unique.3

Functional JavaScript

Oliver Steele’s Functional JavaScript library is the first functional library that I discovered; about 4-5 years ago.4 It provides all of the normal higher-order functions like map, reduce and filter. For example, to square the numbers in an array one would normally write the following:

function square(n) { return n * n }

map(square, [1, 2, 3, 4]);
//=> [1, 4, 9, 16]

This is known technology by now, but at the time of its release, Functional JavaScript was fostering a style of programming that hadn’t gained a foothold in the larger JavaScript community.5

However, something that Functional JavaScript provided, that to this day has not been fully leveraged6 are its deliciously insane (in a good way) lambda string literals. Using the string lambda feature the same code as above can be written as:

map('n*n', [1, 2, 3, 4]); 
//=> [1, 4, 9, 16]

So as you’ll notice, the whole square function was replaced by the string 'n*n'. The mechanism behind this mojo is pretty interesting to read, so I highly advise studying it deeply to see some true JS-wizardry in action.

In a nutshell, the string lambda is parsed into a string format representing a function’s parameters and body text and passed on to the Function constructor to build a real-life function. The Functional JavaScript core functions will build real functions from string lambdas whenever they’re given a string where a function argument is expected. The one downside of using the string lambda form is that it does not create a closure. Observe that the following code uses a closure to scale an array:

function scale(a, m) { 
  return map(function(n) { return n*m }, a);
}

scale([1,2,3], 10);

//=> [10,20,30]

In short, the m argument is captured by the inner function passed to map and used as the scale factor. The follow, using a string lambda does not build a closure:

function scale(a, m) { 
  return map('n*m', a) ;
}

scale([1,2,3], 10);

//=> [0,2,6]

That’s weird. How did it get those numbers?

The problem is that since a closure cannot be created,7 Functional JavaScript just parses and sets m as another parameter thus building a 2-arg function that is called on every element in the array. As you might have guessed, Functional JavaScript does the same thing as Array#map. That is, when the 2-arg function is called the second argument m is assigned the array index of the current element. Therefore, the actual calculations occurring are:

1*0 //=> 0
2*1 //=> 2
3*2 //=> 6

I could murder that Array#map.

My favorite feature of Functional JavaScript is the interplay between currying and the string lambdas, shown below:

var lessThan5 = rcurry('<', 5);

lessThan5(4); 
//=> true

lessThan5(44); 
//=> false

I’ll cover currying in a later post, but it’s very interesting how the string lambda and currying interoperate to provide very succinct code.

Functional JavaScript is a masterful piece of JavaScript meta-programming8 and well worth exploring for its technical insights alone.

Enjoy.

If you want to talk functional programming, my book, the library in question or anything else then feel free to comment below or email me at the address at the top of this blog post.

:F


  1. I cover a few in an appendix, but did not go as deeply as I would have liked given unlimited time and page count. 

  2. Including, but not limited to: Functional JavaScript by Oliver Steele, Lemonad, RxJS, Bilby, Allong.es, D3, Reducers, Underscore-contrib, Mori and Bacon.js

  3. Seriously, who needs yet another blog post on closures, map, reduce, filter, __proto__ and the like? I’ll hit on those topics from time to time, but they will not be the focus of these posts. 

  4. Although I must have come across BeyondJS at some point during my early LtU lurking. Memory fails me. 

  5. And perhaps FP hasn’t still caught on in the larger JS community, but it’s gaining ground and I hope my book will help in some way

  6. Reginald Braithwaite has extracted the string lambdas from Functional JavaScript into a pointed JS library at https://github.com/raganwald/string-lambdas. Do evil. Enjoy. 

  7. You can see this in action by substituting the string lambda 'n -> n*m' instead — which will just blow up instead of returning the wrong answer. 

  8. I’ve toyed with the idea of writing a JS metaprogramming book, but I think there’s no market for it and besides, I’m burned out on writing for now. 

3 Comments, Comment or Ping

  1. Ramkumar Ramachandra

    Why would you want to use lambda string literals? Won’t it completely break the compiler when it comes to error-handling?

    Take your example:

    map(‘n*n’, [1, 2, 3, 4]);

    The compiler has no knowledge about you wanting to express two arguments to a lambda and then multiplying them. The library does some string manipulation magic, and will have to bend over backwards to emit useful errors.

    Currying is even worse. In the general case, your N-argument function is being partially applied to M arguments (M < N), and the kind of error reporting you will require explodes.

    Take a look at the modern Livescript/Prelude.ls equivalents:

    map ((n) -> n * n), [1, 2, 3, 4] lessThan = (x, y) –> y < x lessThan5 = lessThan 5

    Looking at these examples, doesn’t functional Javascript feel like a lost cause?

  2. I have stumbled upon this lib before but never realized how interesting the lambda strings are, I’m going to check the code, thanks.

    Also, wasn’t Rx.js the predecessor of Bacon.js by the same author? Maybe it is worth covering only Bacon.

    Cheers

  3. Something really cool about string literals: You can express “less than five” directly as ‘< 5’. So you can write:

    var youngsters = filter(‘< 5’, ageList);

Reply to “Fun.js – Functional JavaScript”