Setting Up the Functional Programming Environment - Functional Programming in JavaScript (2015)

Functional Programming in JavaScript (2015)

Chapter 3. Setting Up the Functional Programming Environment

Introduction

Do we need to know advanced math—category theory, Lambda calculus, polymorphisms—just to write applications with functional programming? Do we need to reinvent the wheel? The short answer to both these questions is no.

In this chapter, we will do our best to survey everything that can impact the way we write our functional applications in JavaScript.

· Libraries

· Toolkits

· Development environments

· Functional language that compiles to JavaScript

· And more

Please understand that the current landscape of functional libraries for JavaScript is a very fluid one. Like all aspects of computer programming, the community can change in a heartbeat; new libraries can be adopted and old ones can be abandoned. For instance, during the writing process of this very book, the popular and stable Node.js platform for I/O has been forked by its open source community. Its future is vague.

Therefore, the most important concept to be gained from this chapter is not how to use the current libraries for functional programming, but how to use any library that enhances JavaScript's functional programming method. This chapter will not focus on just one or two libraries, but will explore as many as possible with the goal of surveying all the many styles of functional programming that exist within JavaScript.

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 www.youtube.com/watch?v=m3svKOdZij.

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 nativeArray.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:

o Implement the reflexivity, symmetry and transitivity laws

o Define the equals() method

· Semigroups

o Implement the associativity law

o Define the concat() method

· Monoid

o Implement right identity and left identity

o Define the empty() method

· Functor

o Implement the identity and composition laws

o 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 athttp://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('\n').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('\n').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

o 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

o 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

o Yes, it is named after the infamous rap group Wu Tang Clan

· sloth.js

o Very similar to the Lazy.js libraries, but much smaller

· stream.js

o The stream.js library supports infinite streams and not much else

o Absolutely tiny in size

· Lo-Dash.js

o As the name might imply, the lo-dash.js library was inspired by the underscore.js library

o Highly optimized

· Sugar

o Sugar is a support library for functional programming techniques in JavaScript, like Underscore, but with some key differences in how it's implemented.

o 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.

o Very good documentation, unit tests, analyzers, and more.

· from.js

o A new functional library and LINQ (Language Integrated Query) engine for JavaScript that supports most of the same LINQ functions that .NET provides

o 100% lazy evaluation and supports lambda expressions

o Very young but documentation is excellent

· JSLINQ

o Another functional LINQ engine for JavaScript

o Much older and more mature than from.js library

· Boiler.js

o Another utility library that extends JavaScript's functional methods to more primitives: strings, numbers, objects, collections and arrays

· Folktale

o 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

o 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.

o 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?

Development and production environments

It does not matter in terms of programming style what type of environment the application is being developed in and will be deployed in. But it does matter to the libraries a lot.

Browsers

The majority of JavaScript applications are designed to run on the client side, that is, in the client's browser. Browser-based environments are excellent for development because browsers are ubiquitous, you can work on the code right on your local machine, the interpreter is the browser's JavaScript engine, and all browsers have a developer console. Firefox's FireBug provides very useful error messages and allows for break-points and more, but it's often helpful to run the same code in Chrome and Safari to cross-reference the error output. Even Internet Explorer contains developer tools.

The problem with browsers is that they evaluate JavaScript differently! Though it's not common, it is possible to write code that returns very different results in different browsers. But usually the differences are in the way they treat the document object model and not how prototypes and functions work. Obviously, Math.sqrt(4) method returns 2 to all browsers and shells. But the scrollLeft method depends on the browser's layout policies.

Writing browser-specific code is a waste of time, and that's another reason why libraries should be used.

Server-side JavaScript

The Node.js library has become the standard platform for creating server-side and network-based applications. Can functional programming be used for server-side application programming? Yes! Ok, but do there exist any functional libraries that are designed for this performance-critical environment? The answer to that is also: yes.

All the functional libraries outlined in this chapter will work in the Node.js library, and many depend on the browserify.js module to work with browser elements.

A functional use case in the server-side environment

In our brave new world of network systems, server-side application developers are often concerned with concurrency, and rightly so. The classic example is an application that allows multiple users to modify the same file. But if they try to modify it at the same time, you will get into an ugly mess. This is the maintenance of state problem that has plagued programmers for decades.

Assume the following scenario:

1. One morning, Adam opens a report for editing but he doesn't save it before leaving for lunch.

2. Billy opens the same report, adds his notes, and then saves it.

3. Adam comes back from lunch, adds his notes to the report, and then saves it, unknowingly overwriting Billy's notes.

4. The next day, Billy finds out that his notes are missing. His boss yells at him; everybody gets mad and they gang up on the misguided application developer who unfairly loses his job.

For a long time, the solution to this problem was to create a state about the file. Toggle a lock status to on when someone begins editing it, which prevents others from being able to edit it, and then toggle it to off once they save it. In our scenario, Billy would not be able to do his work until Adam gets back from lunch. And if it's never saved (if, say, Adam decided to quit his job in the middle of the lunch break), then no one will ever be able to edit it.

This is where functional programming's ideas about immutable data and state (or lack thereof) can really be put to work. Instead of having users modify the file directly, with a functional approach they would modify a copy of the file, which is a new revision. If they go to save the revision and a new revision already exists, then we know that someone else has already modified the old one. Crisis averted.

Now the scenario from before would unfold like this:

1. One morning, Adam opens a report for editing. But he doesn't save it before going to lunch.

2. Billy opens the same report, adds his notes, and saves it as a new revision.

3. Adam returns from lunch to add his notes. When he attempts to save the new revision, the application tells him that a newer revision now exists.

4. Adam opens the new revisions, adds his notes to it, and saves another new revision.

5. By looking at the revision history, the boss sees that everything is working smoothly. Everyone is happy and the application developer gets a promotion and a raise.

This is known as event sourcing. There is no explicit state to be maintained, only events. The process is much cleaner and there is a clear history of events that can be reviewed.

This idea and many others are why functional programming in server-side environments is on the rise.

CLI

Although web and the node.js library are the two main JavaScript environments, some pragmatic and adventurous users are finding ways to use JavaScript in the command line.

Using JavaScript as a Command Line Interface (CLI) scripting language might be one of the best opportunities to apply function programming. Imagine being able to use lazy evaluation when searching for local files or to rewrite an entire bash script into a functional JavaScript one-liner.

Using functional libraries with other JavaScript modules

Web applications are made up of all sorts of things: frameworks, libraries, APIs and more. They can work along side each other as dependents, plugins, or just as coexisting objects.

· Backbone.js

o An MVP (model-view-provider) framework with a RESTful JSON interface

o Requires the underscore.js library, Backbone's only hard dependency

· jQuery

o The Bacon.js library has bindings for mixing with jQuery

o Underscore and jQuery complement each other very well

· Prototype JavaScript Framework

o Provides JavaScript with collection functions in the manner closest to Ruby's Enumerable

· Sugar.js

o Modifies native objects and their methods

o Must be careful when mixing with other libraries, especially Prototype

Functional languages that compile into JavaScript

Sometimes the thick veneer of C-like syntax over JavaScript's inner functionality can be enough to make you want to switch to another functional language. Well, you can!

· Clojure and ClojureScript

o Closure is a modern Lisp implementation and a full-featured functional language

o ClojureScript trans-compiles Clojure into JavaScript

· CoffeeScript

o CoffeeScript is the name of both a functional language and a compiler for trans-compiling the language into JavaScript

o 1-to-1 mapping between expressions in CoffeeScript and expression in JavaScript

There are many more out there, including Pyjs, Roy, TypeScript, UHC and more.

Summary

Which library you choose to use depends on what your needs are. Need functional reactive programming to handle events and dynamic values? Use the Bacon.js library. Only need infinite streams and nothing else? Use the stream.js library. Want to complement jQuery with functional helpers? Try the underscore.js library. Need a structured environment for serious ad hoc polymorphism? Check out the bilby.js library. Need a well-rounded tool for functional programming? Use the Lazy.js library. Not happy with any of these options? Write your own!

Any library is only as good as the way it's used. Although a few of the libraries outlined in this chapter have a few flaws, most faults occur somewhere between the keyboard and the chair. It's up to you to use the libraries correctly and to suit your needs.

And if we're importing code libraries into our JavaScript environment, then maybe we can import ideas and principles too. Maybe we can channel The Zen of Python, by Tim Peter:

Beautiful is better than ugly

Explicit is better than implicit.

Simple is better than complex.

Complex is better than complicated.

Flat is better than nested.

Sparse is better than dense.

Readability counts.

Special cases aren't special enough to break the rules.

Although practicality beats purity.

Errors should never pass silently.

Unless explicitly silenced.

In the face of ambiguity, refuse the temptation to guess.

There should be one—and preferably only one—obvious way to do it.

Although that way may not be obvious at first unless you're Dutch.

Now is better than never.

Although never is often better than "right" now.

If the implementation is hard to explain, it's a bad idea.

If the implementation is easy to explain, it may be a good idea.

Namespaces are one honking great idea—let's do more of those!