So you’re using CoffeeScript, great! But are you exploiting all its features? Functional CoffeeScript is fun, but you need some helpers. In this tutorial we’ll cover the most essential functional helpers and techniques to build a solid foundation for your next project. Let’s keep it DRY!

Foundation

To begin we’ll need a few essential functions. Our very first helper is a nop (or noop) or empty function:

nop = -> 0 1 2 nop = ->

An empty function does nothing, duh. But it is useful nonetheless.

Another helper we’re going to need is an identity function, that returns the argument given to it:

id = (x) -> x 0 1 2 id = ( x ) -> x

We’ll see some use cases of nop and id next.

The builtin function let’s us turn any native function into a regular function:

builtin = (f) -> nop.call.bind f 0 1 2 builtin = ( f ) -> nop . call . bind f

We make use of nop to access the generic call method of functions and then bind f (the given native function) to the this value. What this will do is give us back a function that will generate “normal” functions out of “prototype functions”, for example:

toArray = builtin Array::slice f = -> console.log toArray arguments f 1,2,3 # $ [1,2,3] 0 1 2 3 4 5 6 toArray = builtin Array :: slice f = -> console . log toArray arguments f 1 , 2 , 3 # $ [1,2,3]

toArray isn’t very useful in CoffeScript to get a real array from arguments because we have a rest operator ... , but it is useful nonetheless for other operations, such as transforming DOM collections into arrays for example. We’ll keep it around for later.

The variadic helper returns back the arguments as an array when called.

variadic = (as...) -> as 0 1 2 variadic = ( as . . . ) -> as

It is quite useful for composition and point-free abstractions. A simple example:

variadic 1,2,3 #=> [1,2,3] 0 1 2 variadic 1 , 2 , 3 #=> [1,2,3]

apply is the “normal” version of Function::apply :

apply = (f, as...) -> f [].concat.apply([], as)... 0 1 2 apply = ( f , as . . . ) -> f [ ] . concat . apply ( [ ] , as ) . . .

We make sure that the arguments are flattened one level, otherwise we’ll end up with a nested array and the applied function won’t work as expected. We can use apply like:

apply Math.max, [1,2,3] #=> 3 0 1 2 apply Math . max , [ 1 , 2 , 3 ] #=> 3

Higher-order and currying

As you probably know, CoffeeScript functions are objects, with properties and methods, that you can pass around, just like any other object.

With functions as first class citizens we get higher-order functions; the essence of functional CoffeeScript. A higher-order function takes one or many functions as arguments or returns a function. This is the way to do composition, and make your code more declarative.

Our first look at higher-order functions is a very useful helper by the name of notF , which takes a function that returns a boolean, and gives you a function that negates the returned value:

notF = (f) -> (as...) -> not f as... 0 1 2 notF = ( f ) -> ( as . . . ) -> not f as . . .

You could use notF to implement odd if you have even :

even = (x) -> x % 2 is 0 odd = notF even 0 1 2 3 even = ( x ) -> x % 2 is 0 odd = notF even

When you got these powers you need to use them wisely, and for that you need curried functions and partial application.

Currying is a simple concept, where you transform a function that takes two or more arguments into a function of one argument that keeps returning a function of one argument until all arguments have been passed, for example:

# not curried mul = (x, y) -> x * y mul(1,2) # curried mul = (x) -> (y) -> x * y mul(1)(2) # ---^ returns a function that expects one argument # --^ calls that function with `2` and returns the result 0 1 2 3 4 5 6 7 8 9 10 # not curried mul = ( x , y ) -> x * y mul ( 1 , 2 ) # curried mul = ( x ) -> ( y ) -> x * y mul ( 1 ) ( 2 ) # ---^ returns a function that expects one argument # --^ calls that function with `2` and returns the result

A partially applied function is one that has been pre-filled with any number of arguments, but that still has one or more arguments left to be passed, for example:

sum = (x, y) -> x + y # partially applied `sum` with `2` sum2 = (x) -> sum 2, x sum2 2 #=> 4 0 1 2 3 4 5 6 sum = ( x , y ) -> x + y # partially applied `sum` with `2` sum2 = ( x ) -> sum 2 , x sum2 2 #=> 4

These two concepts, “currying” and “partial application”, aren’t incredibly complex and they are very useful in practice, but not as easy to abstract for re-use.

We’ll use curry and partial a lot in this tutorial. Many functional libraries already include these helpers but here’s a possible implementation in CoffeeScript:

ncurry = (n, f, as=[]) -> (bs...) -> bs = as.concat bs if bs.length < n then ncurry n, f, bs else f bs... curry = (f) -> (as...) -> if f.length > as.length then ncurry f.length, f, as else f as... _ = {} # placeholder partial = (f, as...) -> (bs...) -> args = as.concat bs i = args.length while i-- if args[i] is _ args[i] = args.splice(-1)[0] f args... 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ncurry = ( n , f , as = [ ] ) -> ( bs . . . ) -> bs = as . concat bs if bs . length < n then ncurry n , f , bs else f bs . . . curry = ( f ) -> ( as . . . ) -> if f . length > as . length then ncurry f . length , f , as else f as . . . _ = { } # placeholder partial = ( f , as . . . ) -> ( bs . . . ) -> args = as . concat bs i = args . length while i -- if args [ i ] is _ args [ i ] = args . splice ( - 1 ) [ 0 ] f args . . .

Update 11/14/14: The built-in bind can also be used to build a generic curry function:

curry = (f) -> (as...) -> if as.length < f.length f.bind [null, as...]... else f as... 0 1 2 3 4 5 6 curry = ( f ) -> ( as . . . ) -> if as . length < f . length f . bind [ null , as . . . ] . . . else f as . . .

With curry we can turn a function of any number of arguments into its auto-curried version, ie:

sum = curry (x, y) -> x + y sum(1)(2) #=> 3 0 1 2 3 sum = curry ( x , y ) -> x + y sum ( 1 ) ( 2 ) #=> 3

From now on remember that we always need to curry functions of two or more arguments as it will improve code re-use, and simplify composition.

With partial we can apply arguments in any order, using _ as a placeholder for arguments to come:

sum2 = partial sum, 2 sum3 = partial sum, _, 3 sum2 2 #=> 4 sum3 3 #=> 6 0 1 2 3 4 5 6 sum2 = partial sum , 2 sum3 = partial sum , _ , 3 sum2 2 #=> 4 sum3 3 #=> 6

In conclusion, understanding the concepts of currying and partial application is key to using these helpers, even if you don’t understand the implementation.

Composition

Composition in CoffeeScript is easy:

add1 = (x) -> x + 1 by2 = (x) -> x * 2 # compose add1 with by2 add1by2 = (x) -> by2 add1 x add1by2 2 #=> 6 0 1 2 3 4 5 6 7 8 add1 = ( x ) -> x + 1 by2 = ( x ) -> x * 2 # compose add1 with by2 add1by2 = ( x ) -> by2 add1 x add1by2 2 #=> 6

But it’s repetitive; this can be abstracted. You can think of composition as the reduction of many functions to a single function, by calling them in order on the given arguments.

compose = (fs...) -> fs.reduce (f, g) -> (as...) -> f g as... 0 1 2 compose = ( fs . . . ) -> fs . reduce ( f , g ) -> ( as . . . ) -> f g as . . .

Now we can compose functions comfortably:

compose(by2, add1) 2 #=> 6 0 1 2 compose ( by2 , add1 ) 2 #=> 6

Sometimes functions play badly with composition because the arguments are in the wrong order. In such cases you need a helper to switch the arguments around, flip :

# flip function of 2 arguments flip = curry (f, x, y) -> f [y, x]... # flip function of 3 arguments flip3 = curry (f, x, y, z) -> f [z, y, x]... # flip variadic function flipN = (f) -> (as...) -> f as.reverse()... 0 1 2 3 4 5 6 7 8 9 # flip function of 2 arguments flip = curry ( f , x , y ) -> f [ y , x ] . . . # flip function of 3 arguments flip3 = curry ( f , x , y , z ) -> f [ z , y , x ] . . . # flip variadic function flipN = ( f ) -> ( as . . . ) -> f as . reverse ( ) . . .

When flipping a variadic function (function that takes any number of arguments), it is important to remember that currying won’t work as expected, and that you should use partial instead to avoid issues. curry expects a function with a finite number of arguments.

Underscore has a helper called _.chain that lets you write code in a sequence, so it’s easier to read and maintain. With what we have so far we can implement this concept very easily, all we need to do is flip compose so it reads left to right and top to bottom.

# `compose` is a variadic function # so we need to use `flipN` sequence = flipN compose 0 1 2 3 4 # `compose` is a variadic function # so we need to use `flipN` sequence = flipN compose

For example:

sequence(f(1), g(2), h(3)) arg # -----------------------^ a chain # ----^ call the chain on an argument # in Underscore _.chain(arg).f(1).g(2).h(3).value() 0 1 2 3 4 5 6 7 sequence ( f ( 1 ) , g ( 2 ) , h ( 3 ) ) arg # -----------------------^ a chain # ----^ call the chain on an argument # in Underscore _ . chain ( arg ) . f ( 1 ) . g ( 2 ) . h ( 3 ) . value ( )

Types and logic

CoffeeScript’s typeof operator sucks, let’s be honest. But luckily we can get the type of any object using its internal string representation, which returns something like [object Type] , and what we need is the type:

isType = curry (t, x) -> Object::toString.call(x).slice(8,-1) is t 0 1 2 isType = curry ( t , x ) -> Object :: toString . call ( x ) . slice ( 8 , - 1 ) is t

But isType won’t check instances of objects, for that we need another function:

instanceOf = curry (ctor, x) -> x instanceof ctor 0 1 2 instanceOf = curry ( ctor , x ) -> x instanceof ctor

Now that we got the types let’s implement some basic logic operations to be used with composition:

isF = curry (x, y) -> x is y isntF = notF isF gte = curry (x, y) -> y >= x lte = curry (x, y) -> y <= x gt = notF lte lt = notF gte 0 1 2 3 4 5 6 7 isF = curry ( x , y ) -> x is y isntF = notF isF gte = curry ( x , y ) -> y >= x lte = curry ( x , y ) -> y <= x gt = notF lte lt = notF gte

Note that the arguments are flipped in the comparison so we can curry these functions nicely. Remember that the receiver of the operation must always come last, so we can abstract y away from the code.

Arrays and strings

We can implement native array and string methods using the builtin helper, but we need to flip the arguments around to play nice with composition; this is where Underscore got it wrong.

Instead of func(xs, f) (callback last), we need func(f, xs) (callback first), so we can abstract xs away with composition. Otherwise we would need to use partial application everywhere, and that’s not fun nor readable. Underscore provides _.chain to mitigate this problem, but it’s still a bit verbose.

Let’s start with arrays:

each = flip builtin Array::forEach map = flip builtin Array::map filter = flip builtin Array::filter fold = flip3 builtin Array::reduce all = flip builtin Array::every any = flip builtin Array::some reverse = builtin Array::reverse join = flip builtin Array::join 0 1 2 3 4 5 6 7 8 9 each = flip builtin Array :: forEach map = flip builtin Array :: map filter = flip builtin Array :: filter fold = flip3 builtin Array :: reduce all = flip builtin Array :: every any = flip builtin Array :: some reverse = builtin Array :: reverse join = flip builtin Array :: join

Note that if the method has one argument you use flip , but if it has two arguments you use flip3 , that’s because the receiver counts as one more argument. In xs.reduce(f, acc) , by doing fold = flip3 builtin Array::reduce we get a function like fold(acc, f, xs) , great for currying and composition.

We can do the same with strings:

split = flip builtin String::split match = flip builtin String::match replace = flip3 builtin String::replace search = flip builtin String::search substr = flip3 builtin String::substr trim = builtin String::trim toUpper = builtin String::toUpperCase toLower = builtin String::toLowerCase 0 1 2 3 4 5 6 7 8 9 split = flip builtin String :: split match = flip builtin String :: match replace = flip3 builtin String :: replace search = flip builtin String :: search substr = flip3 builtin String :: substr trim = builtin String :: trim toUpper = builtin String :: toUpperCase toLower = builtin String :: toLowerCase

You can see that methods that don’t take arguments, such as trim don’t need to be flipped, because the function that we get back from builtin has only one argument, the receiver.

To check for items in an array we’ll use CoffeeScript’s in operator wraped in a curried function:

inArray = curry (x, xs) -> x in xs 0 1 2 inArray = curry ( x , xs ) -> x in xs

We could have implemented inArray by borrowing the native indexOf and using composition:

inArray = compose gt(-1), flip builtin Array::indexOf 0 1 2 inArray = compose gt ( - 1 ) , flip builtin Array :: indexOf

But it isn’t necessarily more readable to do it this way, so we’ll just keep the first version.

Now let’s slice those arrays! As Array::slice can take an optional argument we won’t use builtin . We’ll make a function that plays nice with partial application by adapting the logic depending on a nullable argument:

slice = curry (i, j, xs) -> if j? then xs[i...j] else xs[i..] 0 1 2 slice = curry ( i , j , xs ) -> if j ? then xs [ i . . . j ] else xs [ i . . ]

By currying slice and using CoffeeScript’s destructuring features we can create most common functions for extracting items and cropping arrays:

first = ([x, xs...]) -> x last = ([xs..., x]) -> x rest = slice 1, null initial = slice 0, -1 take = slice 0 drop = partial slice, _, null, _ 0 1 2 3 4 5 6 7 first = ( [ x , xs . . . ] ) -> x last = ( [ xs . . . , x ] ) -> x rest = slice 1 , null initial = slice 0 , - 1 take = slice 0 drop = partial slice , _ , null , _

We’re done with built-in functions and wrappers. Now we need to implement some common helpers found in Underscore and other libraries to work with arrays and collections.

First let’s create the inverse of filter so we can filter elements out. We can simply negate the filter function to achieve this:

reject = curry (f, xs) -> filter notF(f), xs 0 1 2 reject = curry ( f , xs ) -> filter notF ( f ) , xs

Then we need flatten , an essential array operation that will let us build other helpers with composition:

flatten = (xs) -> flat = [].concat.apply [], xs if xs.some Array.isArray then flatten flat else flat 0 1 2 3 4 flatten = ( xs ) -> flat = [ ] . concat . apply [ ] , xs if xs . some Array . isArray then flatten flat else flat

flatten uses recursion to flatten deep nested arrays.

It is quite common to want to filter out duplicates, but to keep them too:

unique = (xs) -> xs.filter (x, i) -> xs.indexOf(x) is i dups = (xs) -> xs.filter (x, i) -> xs.indexOf(x) isnt i 0 1 2 3 unique = ( xs ) -> xs . filter ( x , i ) -> xs . indexOf ( x ) is i dups = ( xs ) -> xs . filter ( x , i ) -> xs . indexOf ( x ) isnt i

Finally an operation that can be performed in arrays that’s quite handy is zipping:

zip = (xss...) -> xss[0].map (_, i) -> xss.map (xs) -> xs[i] 0 1 2 zip = ( xss . . . ) -> xss [ 0 ] . map ( _ , i ) -> xss . map ( xs ) -> xs [ i ]

A zip takes any number of arrays an combines it’s elements by zipping each element in same index position from each array, for example:

zip [1,2], [3,4], [5,6] #=> [[1,3,5], [2,4,6]] 0 1 2 zip [ 1 , 2 ] , [ 3 , 4 ] , [ 5 , 6 ] #=> [[1,3,5], [2,4,6]]

Zipping can also be performed with a callback to do something with the zipped items:

zipWith = (f, xs...) -> map partial(apply, f), apply zip, xs 0 1 2 zipWith = ( f , xs . . . ) -> map partial ( apply , f ) , apply zip , xs

Using zipWith we can do the following:

add = (x, y) -> x + y zipWith add, [1,2], [3,4] #=> [4,6] 0 1 2 3 add = ( x , y ) -> x + y zipWith add , [ 1 , 2 ] , [ 3 , 4 ] #=> [4,6]

Objects

Objects are not as well abstracted for iteration as arrays are in CoffeeScript. Other than the of and own operators there aren’t any built-in functions to reduce an object, or get an array of values for example.

To fold an object we can loop and keep track of an accummulator that it’s passed in every call to the given callback. This is like Array::reduce for objects:

forOwn = curry (acc, f, obj) -> i = 0 for own k, v of obj acc = f [acc, k, v, i++]... acc 0 1 2 3 4 5 6 forOwn = curry ( acc , f , obj ) -> i = 0 for own k , v of obj acc = f [ acc , k , v , i ++ ] . . . acc

With forOwn we can sum the values of an object for example:

obj = {a:1, b:2, c:3} sum = (acc, key, val) -> acc += val acc forOwn 0, sum, obj #=> 6 0 1 2 3 4 5 6 7 8 obj = { a : 1 , b : 2 , c : 3 } sum = ( acc , key , val ) -> acc += val acc forOwn 0 , sum , obj #=> 6

Keep in mind that the order of properties of an object isn’t guaranteed by the ECMA spec and it’s up to the vendor to implement it. Although in most browsers and NodeJS it does output the properties in order most of the time, but don’t count on it. If your operation is commutative then it doesn’t matter, like in the case of addition, or multiplication.

We can curry forOwn to create a helper to transform an object into an array of key-value pairs:

pairs = forOwn [], (acc, k, v) -> acc.concat [[k,v]] 0 1 2 pairs = forOwn [ ] , ( acc , k , v ) -> acc . concat [ [ k , v ] ]

And then use pairs like:

pairs {a:1, b:2} #=> [['a',1], ['b',2]] 0 1 2 pairs { a : 1 , b : 2 } #=> [['a',1], ['b',2]]

Another operation we can do by currying forOwn is unziping an object, that is taking the keys in one array and the values on another:

unzipObject = forOwn [[],[]], (acc, k, v, i) -> acc[0][i] = k; acc[1][i] = v acc 0 1 2 3 4 unzipObject = forOwn [ [ ] , [ ] ] , ( acc , k , v , i ) -> acc [ 0 ] [ i ] = k ; acc [ 1 ] [ i ] = v acc

For example:

obj = {a:1, b:2} keys = unzipObject(obj)[0] #=> ['a', 'b'] values = unzipObject(obj)[1] #=> [1, 2] 0 1 2 3 4 obj = { a : 1 , b : 2 } keys = unzipObject ( obj ) [ 0 ] #=> ['a', 'b'] values = unzipObject ( obj ) [ 1 ] #=> [1, 2]

Extracting a property is a very common operation on objects. Underscore has two functions for doing this: _.pluck and _.property . But with currying we can implement this functionality more efficiently. First, instead of two functions we’ll have just one that can be partially applied to a mapping operation if needed. Second, instead of taking a single property we can lookup full paths in objects by using a string like 'a.b.c' :

pluck = curry (x, xs) -> String(x).split('.').reduce (acc, x) -> if x of Object acc then acc[x] else undefined ,xs 0 1 2 3 4 5 pluck = curry ( x , xs ) -> String ( x ) . split ( '.' ) . reduce ( acc , x ) -> if x of Object acc then acc [ x ] else undefined , xs

We use Object acc to make sure the of operator works on literals like strings, which aren’t really objects, but primitives that get wrapped in an object when used.

Now we can use it with single properties, full paths and mapping:

pluck 'a', {a:1, b:2} #=> 1 pluck 'a.b.c', {a:{b:{c:1}}} #=> 1 map pluck('length'), ['one','two','three'] #=> [3,3,5] 0 1 2 3 4 pluck 'a' , { a : 1 , b : 2 } #=> 1 pluck 'a.b.c' , { a : { b : { c : 1 } } } #=> 1 map pluck ( 'length' ) , [ 'one' , 'two' , 'three' ] #=> [3,3,5]

Another not so common, but still useful operation on objects is to lookup properties recursively, which we can do using a comprehension and our previous pluck helper:

pluckR = curry (x, xs) -> (xs while xs = pluck x, xs) 0 1 2 pluckR = curry ( x , xs ) -> ( xs while xs = pluck x , xs )

The DOM is a classic example of recursive plucking:

# given: # <ul> # <li>A</li> # <li>B</li> # <li>C</li> # </ul> el = document.querySelector 'li:first-child' #=> <li>A</li> # will return all next siblings nextAll = pluckR 'nextElementSibling' nextAll els #=> [<li>B</li>, <li>C</li>] 0 1 2 3 4 5 6 7 8 9 10 11 12 13 # given: # <ul> # <li>A</li> # <li>B</li> # <li>C</li> # </ul> el = document . querySelector 'li:first-child' #=> <li>A</li> # will return all next siblings nextAll = pluckR 'nextElementSibling' nextAll els #=> [<li>B</li>, <li>C</li>]

With our plucking and iteration object helpers we can implement many other functions, here’s a few:

size = compose pluck('length'), Object.keys # transforms an array like [a, 1, b, 2] # into and object {a:1, b:2} toObject = (xs) -> xs.reduce (acc, x, i) -> acc[xs[i-1]] = x if i % 2 acc ,{} # the opposite of `unzipObject` zipObject = compose toObject, flatten, zip # Check if a property is defined in an object # using `pluck` to be able to search by path has = compose notF(isType('Undefined')), pluck 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 size = compose pluck ( 'length' ) , Object . keys # transforms an array like [a, 1, b, 2] # into and object {a:1, b:2} toObject = ( xs ) -> xs . reduce ( acc , x , i ) -> acc [ xs [ i - 1 ] ] = x if i % 2 acc , { } # the opposite of `unzipObject` zipObject = compose toObject , flatten , zip # Check if a property is defined in an object # using `pluck` to be able to search by path has = compose notF ( isType ( 'Undefined' ) ) , pluck

Conclusion

With a handful of helpers we can ease the transition into functional programming with CoffeeScript. Currying, partial application and composition are key to building higher abstractions, and writing beautiful declarative terse code.

The possibilities are now endless, with a solid foundation the good one liners come naturally, take a look:

compact = filter Boolean flatMap = flip compose flatten, map union = compose unique, flatten, variadic intersection = compose unique, dups, flatten, variadic difference = (xs, as...) -> reject inArray(unique(flatten as)), xs partition = curry (f, xs) -> [filter(f, xs), reject f, xs] words = split ' ' unwords = join ' ' # and more... 0 1 2 3 4 5 6 7 8 9 10 compact = filter Boolean flatMap = flip compose flatten , map union = compose unique , flatten , variadic intersection = compose unique , dups , flatten , variadic difference = ( xs , as . . . ) -> reject inArray ( unique ( flatten as ) ) , xs partition = curry ( f , xs ) -> [ filter ( f , xs ) , reject f , xs ] words = split ' ' unwords = join ' ' # and more...

For more check out Essential.js, a library built in CoffeeScript using all of these concepts.

For even more functional goodies check out LiveScript and its official library Preludels.