#+TITLE: Functional Programming in JavaScript
#+PROPERTY: :html-toplevel-hlevel 1
#+PROPERTY: :with-toc 0
* Why?

Imperative programming is concerned with *how*

Functional programming is concerned with *what*

* Concepts

 - First-class Functions
 - Higher-order Functions
 - Recursion
 - Pure functions
 - Currying & Partial Application

* Further concepts

 - Lazy Evaluation
 - Types & Data Structures
 - Category Theory

* First-class functions

 - Have no restriction on their use
 - Are values
 - Enable the use of callback functions in JavaScript



#+BEGIN_SRC js
const fn = function () {
  return 2
}
#+END_SRC


* Higher-order functions

Functions that operate on other functions are higher-order functions



#+BEGIN_SRC js
const succ = function (x) {
  return x + 1
}

const arr = [1, 2, 3, 4]

arr.map(succ)
#+END_SRC

Here, =Array.prototype.map= is the higher-order function

* Higher-order functions (cont.)

Functions that return functions are also higher-order functions



#+BEGIN_SRC js
function adder (n) {
  return function (x) {
    return n + x
  }
}

const add1 = adder(1)
#+END_SRC

=adder= is a higher-order function

* Pure functions

Functions without side-effects

#+BEGIN_SRC js
const succ = (x) => x + 1

console.log(succ(succ(1)))

// could be optimised away by a compiler, e.g.:

console.log(3)
#+END_SRC

* Recursion

Functions that call themselves

#+BEGIN_SRC js
function fibonacci (n) {
  switch (n) {
    case 0:
    case 1:
      return 1
    default: 
      return fibonacci(n - 1) + fibonacci(n - 2)
  }
}
#+END_SRC

* Partial application

The infamous =Function.prototype.bind= in JavaScript

#+BEGIN_SRC js
function add (x, y) {
  return x + y
}

const add1 = add.bind(add, 1)

add1(3) // = 4
#+END_SRC

* Partial application (cont.)

After ES6 introduced arrow functions, partial application has become
more popular

#+BEGIN_SRC js
const add = x => y => x + y
#+END_SRC

* Currying

Related to partial application, but more implicit and general

Translates */1/ function of arity /n/* to */n/ functions of arity /1/*

#+BEGIN_SRC js
function volume (w, d, h) {
  return w * d * h
}

const vol = curry(volume)
vol(10)(20)(30)
// is strictly equivalent to
volume(10, 20, 30)
#+END_SRC

* Easy Currying

In order to make currying (and partial application) easier to use,
move the *most important* argument to a function to the end:

#+BEGIN_SRC js
const badMap = (arr, fn) => arr.map(fn)
const goodMap = (fn, arr) => arr.map(fn)
const curriedBadMap = curry(badmap)
const curriedGoodMap = curry(goodMap)

const goodDoubleArray = goodMap(x => x * 2)
const badDoubleArray = badMap(_, x => x * 2)
#+END_SRC

The bad version requires the curry function to support a magic
placeholder argument and doesn't look as clean.

* Practical Currying

Currying is not automatic in JavaScript, as in other languages

External tools don't (currently) to statically analyse curried
functions

Solution: Don't expose curried functions
Instead, write functions as if currying were automatic

* Functional composition

Creating functions from other functions

Usually provided by =compose= (right-to-left) and =pipe= (left-to-right)

A very simple definition of =compose= for only two functions would look like this

#+BEGIN_SRC js
function compose (f, g) {
  return function (...args) {
    return f(g(...args))
  }
}
#+END_SRC

* Functional composition (cont.)

#+BEGIN_SRC js
const plusOne = x => x + 1
const timesTwo = x => x * 2

const plusOneTimesTwo = compose(timesTwo, plusOne)
const timesTwoPlusOne = compose(plusOne, timesTwo)

nextDoubled(3) // = (3 + 1) * 2 = 8
timesTwoPlusOne(3) // = (3 * 2) + 1 = 7
#+END_SRC

* pipe

What about =pipe=?

=pipe= does the same thing, but runs the functions the other way around

=pipe(f, g)= is the same as =compose(g, f)=

* Point-free programming

With currying and higher-order functions, we (often) don't need to declare function arguments

#+BEGIN_SRC js
const modulo = a => b => b % a
const eq = a => b => a === b

const isEven = x => eq(0)(modulo(2)(x))
const isEvenPointFree = compose(eq(0), modulo(2))
#+END_SRC

* Further Resources

- [[https://drboolean.gitbooks.io/mostly-adequate-guide/content/][Mostly adequate guide to FP (in javascript)]]
- [[http://ramdajs.com/][Ramda]], a general-purpose FP library
- [[https://sanctuary.js.org/][Sanctuary]], a JavaScript library for Haskellers