Let's Make a Framework: Functional Programming Part 2

2010-03-25 00:00:00 +0000 by Alex R. Young

Welcome to part 5 of Let's Make a Framework, the ongoing series about
building a JavaScript framework. This part continues the work last week
on functional programming.

If you haven't been following along, these articles are tagged with
lmaf. The project we're creating is called Turing and is available on GitHub:
turing.js. You can contribute! Fork and message me with your changes.

More Functional Methods

Last week I intimated that each formed the basis of our
functional programming library. This week I'll show you how to add more
methods that build on each. I'll draw on inspiration from
Underscore and Prototype, not to mention JavaScript's more recent Array.prototype methods.


Filter allows you to remove values from a list:

turing.enumerable.filter([1, 2, 3, 4, 5, 6], function(n) { return n % 2 == 0; });
// 2,4,6

That means the implementation needs to:

  1. Check if there's a native filter method and use it if
  2. Else use turing.enumerable.each
  3. Filter objects into multi-dimensional arrays if required

The tests need to check that both arrays and objects are handled. We
already used this approach last week:

Riot.context('turing.enumerable.js', function() {
  given('an array', function() {
    var a = [1, 2, 3, 4, 5];

    should('filter arrays', function() {
      return turing.enumerable.filter(a, function(n) { return n % 2 == 0; });
    }).equals([2, 4]);

  given('an object', function() {
    var obj = { one: '1', two: '2', three: '3' };

    should('filter objects and return a multi-dimensional array', function() {
      return turing.enumerable.filter(obj, function(v, i) { return v < 2; })[0][0];

I've tried to be sensible about handling both objects and arrays.
Underscore supports filtering objects, but returns a slightly different
result (it just returns the value instead of key/value).


Detect is slightly different to filter because there isn't
an ECMAScript method. It's easy to use though:

turing.enumerable.detect(['bob', 'sam', 'bill'], function(name) { return name === 'bob'; });
// bob

This class of methods is interesting because it requires an early break.
You may have noticed that the each method had some
exception handling that checked for Break:

each: function(enumerable, callback, context) {
  try {
    // The very soul of each
  } catch(e) {
    if (e != turing.enumerable.Break) throw e;

  return enumerable;

Detect simply uses each with the user-supplied callback,
until a truthy value is returned. Then it throws a Break.


We need to be able to chain these calls if we can honestly say turing.js
is useful. Chaining is natural when you've overridden
Array.prototype like some libraries do, but seeing as we're
being good namespacers we need to create an API for it.

I'd like it to look like this (which is different to Underscore):

turing.enumerable.chain([1, 2, 3, 4]).filter(function(n) { return n % 2 == 0; }).map(function(n) { return n * 10; }).values();

Chained functions are possible when each function returns an object that
can be used to call the next one. If this looks confusing to you, it
might help to break it down:

.chain([1, 2, 3, 4])                         // Start a new "chain" using an array
.filter(function(n) { return n % 2 == 0; })  // Filter out odd numbers
.map(function(n) { return n * 10; })         // Multiply each number by 10
.values();                                   // Fetch the values

To make this possible we need a class with the following features:

This is all easily possible using closures and apply:

// store temporary values in this.results
turing.enumerable.Chainer = turing.Class({
  initialize: function(values) {
    this.results = values;

  values: function() {
    return this.results;

// Map selected methods by wrapping them in a closure that returns this each time
turing.enumerable.each(['map', 'detect', 'filter'], function(methodName) {
  var method = turing.enumerable[methodName];
  turing.enumerable.Chainer.prototype[methodName] = function() {
    var args = Array.prototype.slice.call(arguments);
    this.results = method.apply(this, args);
    return this;


Now you know how to:

If you'd like to implement more enumerable methods, check out the ones
that Underscore supports
and port them to turing's style and naming conventions. Add a test or
two, let me know via GitHub,
and I'll include your contribution and add you to the contributor list.