Functional libraries for JavaScript

It's been said that every functional programmer writes their own library of functions, and functional JavaScript programmers are no exception. With today's open source code-sharing platforms such as GitHub, Bower, and NPM, it's easier to share, collaborate, and grow these libraries. Many libraries exist for functional programming with JavaScript, ranging from tiny toolkits to monolithic module libraries.

Each library promotes its own style of functional programming. From a rigid, math-based style to a relaxed, informal style, each library is different but they all share one common feature: they all have abstract JavaScript functional capabilities to increase code re-use, readability, and robustness.

At the time of writing, however, a single library has not established itself as the de-facto standard. Some might argue that underscore.js is the one but, as you'll see in the following section, it might be advisable to avoid underscore.js.

Underscore.js

Underscore has become the standard functional JavaScript library in the eyes of many. It is mature, stable, and was created by Jeremy Ashkenas, the man behind the Backbone.js and CoffeeScript libraries. Underscore is actually a reimplementation of Ruby's Enumerable module, which explains why CoffeeScript was also influenced by Ruby.

Similar to jQuery, Underscore doesn't modify native JavaScript objects and instead uses a symbol to define its own object: the underscore character "_". So, using Underscore would work like this:

var x = _.map([1,2,3], Math.sqrt); // Underscore's map function
console.log(x.toString());

We've already seen JavaScrip's native map() method for the Array object, which works like this:

var x = [1,2,3].map(Math.sqrt);

The difference is that, in Underscore, both the Array object and the callback() function are passed as parameters to the Underscore object's map() method (_.map), as opposed to passing only the callback to the array's native map() method (Array.prototype.map).

But there's way more than just map() and other built-in functions to Underscore. It's full of super handy functions such as find(), invoke(), pluck(), sortyBy(), groupBy(), and more.

var greetings = [{origin: 'spanish', value: 'hola'}, 
{origin: 'english', value: 'hello'}];
console.log(_.pluck(greetings, 'value')  );
// Grabs an object's property.
// Returns: ['hola', 'hello']
console.log(_.find(greetings, function(s) {return s.origin == 
'spanish';}));
// Looks for the first obj that passes the truth test
// Returns: {origin: 'spanish', value: 'hola'}
greetings = greetings.concat(_.object(['origin','value'],
['french','bonjour']));
console.log(greetings);
// _.object creates an object literal from two merged arrays
// Returns: [{origin: 'spanish', value: 'hola'},
//{origin: 'english', value: 'hello'},
//{origin: 'french', value: 'bonjour'}]

And it provides a way of chaining methods together:

var g = _.chain(greetings)
  .sortBy(function(x) {return x.value.length})
  .pluck('origin')
  .map(function(x){return x.charAt(0).toUpperCase()+x.slice(1)})
  .reduce(function(x, y){return x + ' ' + y}, '')
  .value();
// Applies the functions 
// Returns: 'Spanish English French'
console.log(g);

Note

The _.chain() method returns a wrapped object that holds all the Underscore functions. The _.value method is then used to extract the value of the wrapped object. Wrapped objects are also very useful for mixing Underscore with object-oriented programming.

Despite its ease of use and adaptation by the community, the underscore.js library has been criticized for forcing you to write overly verbose code and for encouraging the wrong patterns. Underscore's structure may not be ideal or even function!

Until version 1.7.0, released shortly after Brian Lonsdorf's talk entitled Hey Underscore, you're doing it wrong!, landed on YouTube, Underscore explicitly prevented us from extending functions such as map(), reduce(), filter(), and more.

_.prototype.map = function(obj, iterate, [context]) {
  if (Array.prototype.map && obj.map === Array.prototype.map) return obj.map(iterate, context);
  // ...
};

Note

You can watch the video of Brian Lonsdorf's talk at https://www.youtube.com/watch?v=m3svKOdZijA.

Map, in terms of category theory, is a homomorphic functor interface (more on this in Chapter 5, Category Theory). And we should be able to define map as a functor for whatever we need it for. So that's not very functional of Underscore.

And because JavaScript doesn't have built-in immutable data, a functional library should be careful to not allow its helper functions to mutate the objects passed to it. A good example of this problem is shown below. The intention of the snippet is to return a new selected list with one option set as the default. But what actually happens is that the selected list is mutated in place.

function getSelectedOptions(id, value) {
  options = document.querySelectorAll('#' + id + ' option'),
  var newOptions = _.map(options, function(opt){
    if (opt.text == value) {
      opt.selected = true;
      opt.text += ' (this is the default)';
    }
    else {
      opt.selected = false;
    }
    return opt;
  });
  return newOptions;
}
var optionsHelp = getSelectedOptions('timezones', 'Chicago'),

We would have to insert the line opt = opt.cloneNode(); to the callback() function to make a copy of each object within the list being passed to the function. Underscore's map() function cheats to boost performance, but it is at the cost of functional feng shui. The native Array.prototype.map() function wouldn't require this because it makes a copy, but it also doesn't work on nodelist collections.

Underscore may be less than ideal for mathematically-correct, functional programming, but it was never intended to extend or transform JavaScript into a pure functional language. It defines itself as a JavaScript library that provides a whole mess of useful functional programming helpers. It may be a little more than a spurious collection of functional-like helpers, but it's no serious functional library either.

Is there a better library out there? Perhaps one that is based on mathematics?

Fantasy Land

Sometimes, the truth is stranger than fiction.

Fantasy Land is a collection of functional base libraries and a formal specification for how to implement "algebraic structures" in JavaScript. More specifically, Fantasy Land specifies the interoperability of common algebraic structures, or algebras for short: monads, monoids, setoids, functors, chains, and more. Their names may sound scary, but they're just a set of values, a set of operators, and some laws it must obey. In other words, they're just objects.

Here's how it works. Each algebra is a separate Fantasy Land specification and may have dependencies on other algebras that need to be implemented.

Fantasy Land

Some of the algebra specifications are:

  • Setoids:
    • Implement the reflexivity, symmetry and transitivity laws
    • Define the equals() method
  • Semigroups
    • Implement the associativity law
    • Define the concat() method
  • Monoid
    • Implement right identity and left identity
    • Define the empty() method
  • Functor
    • Implement the identity and composition laws
    • Define the map() method

The list goes on and on.

We don't necessarily need to know exactly what each algebra is for but it certainly helps, especially if you're writing your own library that conforms to the specifications. It's not just abstract nonsense, it outlines a means of implementing a high-level abstraction called category theory. A full explanation of category theory can be found in Chapter 5, Category Theory.

Fantasy Land doesn't just tell us how to implement functional programming, it does provide a set of functional modules for JavaScript. However, many are incomplete and documentation is pretty sparse. But Fantasy Land isn't the only library out there to implement its open source specifications. Others have too, namely: Bilby.js.

Bilby.js

What the heck is a bilby? No, it's not a mythical creature that might exist in Fantasy Land. It exists here on Earth as a freaky/cute cross between a mouse and a rabbit. Nonetheless, bibly.js library is compliant with Fantasy Land specifications.

In fact, bilby.js is a serious functional library. As its documentation states, it is, Serious, meaning it applies category theory to enable highly abstract code. Functional, meaning it enables referentially transparent programs. Wow, that is pretty serious. The documentation located at http://bilby.brianmckenna.org/ goes on to say that it provides:

  • Immutable multi-methods for ad-hoc polymorphism
  • Functional data structures
  • Operator overloading for functional syntax
  • Automated specification testing (ScalaCheck, QuickCheck)

By far the most mature library that conforms to the Fantasy Land specifications for algebraic structures, Bilby.js is a great resource for fully committing to the functional style.

Let's try an example:

// environments in bilby are immutable structure for multimethods
var shapes1 = bilby.environment()
  // can define methods
  .method(
    'area', // methods take a name
    function(a){return typeof(a) == 'rect'}, // a predicate
    function(a){return a.x * a.y} // and an implementation
  )
  // and properties, like methods with predicates that always
  // return true
  .property(
     'name',   // takes a name
     'shape'), // and a function
// now we can overload it
var shapes2 = shapes1
  .method(
    'area', function(a){return typeof(a) == 'circle'},
    function(a){return a.r * a.r * Math.PI} );
var shapes3 = shapes2
  .method(
    'area', function(a){return typeof(a) == 'triangle'},
    function(a){return a.height * a.base / 2} );

// and now we can do something like this
var objs = [{type:'circle', r:5}, {type:'rect', x:2, y:3}];
var areas = objs.map(shapes3.area);

// and this
var totalArea = objs.map(shapes3.area).reduce(add);

This is category theory and ad-hoc polymorphism in action. Again, category theory will be covered in full in Chapter 5, Category Theory.

Note

Category theory is a recently invigorated branch of mathematics that functional programmers use to maximize the abstraction and usefulness of their code. But there is a major drawback: it's difficult to conceptualize and quickly get started with.

The truth is that Bilby and Fantasy Land are really stretching the possibilities of functional programming in JavaScript. Although it's exciting to see the evolution of computer science, the world may just not be ready for the kind of hard-core functional style that Bibly and Fantasy Land are pushing.

Maybe such a grandiose library on the bleeding-edge of functional JavaScript is not our thing. After all, we set out to explore the functional techniques that complement JavaScript, not to build functional programming dogma. Let's turn our attention to another new library, Lazy.js.

Lazy.js

Lazy is a utility library more along the lines of the underscore.js library but with a lazy evaluation strategy. Because of this, Lazy makes the impossible possible by functionally computing results of series that won't be available with immediate interpretation. It also boasts a significant performance boost.

The Lazy.js library is still very young. But it has a lot of momentum and community enthusiasm behind it.

The idea is that, in Lazy, everything is a sequence that we can iterate over. Owing to the way the library controls the order in which methods are applied, many really cool things can be achieved: asynchronous iteration (parallel programming), infinite sequences, functional reactive programming, and more.

The following examples show off a bit of everything:

// Get the first eight lines of a song's lyrics
var lyrics = "Lorem ipsum dolor sit amet, consectetur adipiscing eli
// Without Lazy, the entire string is first split into lines
console.log(lyrics.split('
').slice(0,3)); 

// With Lazy, the text is only split into the first 8 lines
// The lyrics can even be infinitely long!
console.log(Lazy(lyrics).split('
').take(3));

//First 10 squares that are evenly divisible by 3
var oneTo1000 = Lazy.range(1, 1000).toArray(); 
var sequence = Lazy(oneTo1000)
  .map(function(x) { return x * x; })
  .filter(function(x) { return x % 3 === 0; })
  .take(10)
  .each(function(x) { console.log(x); });

// asynchronous iteration over an infinite sequence
var asyncSequence = Lazy.generate(function(x){return x++})
  .async(100) // 0.100s intervals between elements
  .take(20) // only compute the first 20  
  .each(function(e) { // begin iterating over the sequence
    console.log(new Date().getMilliseconds() + ": " + e);
  });

More examples and use-cases are covered in Chapter 4, Implementing Functional Programming Techniques in JavaScript.

But its not entirely correct to fully credit the Lazy.js library with this idea. One of its predecessors, the Bacon.js library, works in much the same way.

Bacon.js

The logo of Bacon.js library is as follows:

Bacon.js

The mustachioed hipster of functional programming libraries, Bacon.js is itself a library for functional reactive programming. Functional reactive programming just means that functional design patterns are used to represent values that are reactive and always changing, like the position of the mouse on the screen, or the price of a company's stock. In the same way that Lazy can get away with creating infinite sequences by not calculating the value until it's needed, Bacon can avoid having to calculate ever-changing values until the very last second.

What are called sequences in Lazy are known as EventStreams and Properties in Bacon because they're more suited for working with events (onmouseover, onkeydown, and so on) and reactive properties (scroll position, mouse position, toggles, and so on).

Bacon.fromEventTarget(document.body, "click")
  .onValue(function() { alert("Bacon!") });

Bacon is a little bit older than Lazy but its feature set is about half the size and its community enthusiasm is about equal.

Honorable mentions

There are simply too many libraries out there to do them all justice within the scope of this book. Let's look at a few more libraries for functional programming in JavaScript.

  • Functional
    • Possibly the first library for functional programming in JavaScript, Functional is a library that includes comprehensive higher-order function support as well as string lambdas
  • wu.js
    • Especially prized for its curryable() function, wu.js library is a very nice Library for functional programming. It was the first library (that I know of) to implement lazy evaluation, getting the ball rolling for Bacon.js, Lazy.js and other libraries
    • Yes, it is named after the infamous rap group Wu Tang Clan
  • sloth.js
    • Very similar to the Lazy.js libraries, but much smaller
  • stream.js
    • The stream.js library supports infinite streams and not much else
    • Absolutely tiny in size
  • Lo-Dash.js
    • As the name might imply, the lo-dash.js library was inspired by the underscore.js library
    • Highly optimized
  • Sugar
    • Sugar is a support library for functional programming techniques in JavaScript, like Underscore, but with some key differences in how it's implemented.
    • Instead of doing _.pluck(myObjs, 'value') in Underscore, it's just myObjs.map('value') in Sugar. This means that it modifies native JavaScript objects, so there is a small risk of it not playing nicely with other libraries that do the same such as Prototype.
    • Very good documentation, unit tests, analyzers, and more.
  • from.js
    • A new functional library and LINQ (Language Integrated Query) engine for JavaScript that supports most of the same LINQ functions that .NET provides
    • 100% lazy evaluation and supports lambda expressions
    • Very young but documentation is excellent
  • JSLINQ
    • Another functional LINQ engine for JavaScript
    • Much older and more mature than from.js library
  • Boiler.js
    • Another utility library that extends JavaScript's functional methods to more primitives: strings, numbers, objects, collections and arrays
  • Folktale
    • Like the Bilby.js library, Folktale is another new library that implements the Fantasy Land specifications. And like its forefather, Folktale is also a collection of libraries for functional programming in JavaScript. It's very young but could have a bright future.
  • jQuery
    • Surprised to see jQuery mentioned here? Although jQuery is not a tool used to perform functional programming, it nevertheless is functional itself. jQuery might be one of the most widely used libraries that has its roots in functional programming.
    • The jQuery object is actually a monad. jQuery uses the monadic laws to enable method chaining:
      $('#mydiv').fadeIn().css('left': 50).alert('hi!'),

A full explanation of this can be found in Chapter 7, Functional and Object-oriented Programming in JavaScript.

  • And some of its methods are higher-order:
    $('li').css('left': function(index){return index*50});
  • As of jQuery 1.8, the deferred.then parameter implements a functional concept known as Promises.
  • jQuery is an abstraction layer, mainly for the DOM. It's not a framework or a toolkit, just a way to use abstraction to increase code-reuse and reduce ugly code. And isn't that what functional programming is all about?
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
13.58.121.8