Table of Contents
+-
+
- 1. Why? +
- 2. Concepts +
- 3. Further concepts +
- 4. First-class functions +
- 5. Higher-order functions +
- 6. Higher-order functions (cont.) +
- 7. Pure functions +
- 8. Recursion +
- 9. Partial application +
- 10. Partial application (cont.) +
- 11. Currying +
- 12. Easy Currying +
- 13. Practical Currying +
- 14. Functional composition +
- 15. Functional composition (cont.) +
- 16. pipe +
- 17. Point-free programming +
- 18. Further Resources +
1 Why?
++Imperative programming is concerned with how +
+ ++Functional programming is concerned with what +
+2 Concepts
+-
+
- First-class Functions +
- Higher-order Functions +
- Recursion +
- Pure functions +
- Currying & Partial Application +
3 Further concepts
+-
+
- Lazy Evaluation +
- Types & Data Structures +
- Category Theory +
4 First-class functions
+-
+
- Are values +
- Have no restriction on their use +
- Enable the use of callback functions in JavaScript +
+ +
+ +var fn = function () {
+ return 2
+}
+
+5 Higher-order functions
++Functions that operate on other functions are higher-order functions +
+ ++ +
+ +var succ = function (x) {
+ return x + 1
+}
+
+var arr = [1, 2, 3, 4]
+
+arr.map(succ)
+
+
+Here, Array.prototype.map
is the higher-order function
+
6 Higher-order functions (cont.)
++Functions that return functions are also higher-order functions +
+ ++ +
+ +function adder (n) {
+ return function (x) {
+ return n + x
+ }
+}
+
+var add1 = adder(1)
+
+
+adder
is a higher-order function
+
7 Pure functions
++Functions without side-effects +
+ +var succ = (x) => x + 1
+
+console.log(succ(succ(1)))
+
+// could be optimised away by a compiler, e.g.:
+
+console.log(3)
+
+8 Recursion
++Functions that call themselves +
+ +function fibonacci (n) {
+ switch (n) {
+ case 0:
+ case 1:
+ return 1
+ default:
+ return fibonacci(n - 1) + fibonacci(n - 2)
+ }
+}
+
+9 Partial application
+
+The infamous Function.prototype.bind
in JavaScript
+
function add (x, y) {
+ return x + y
+}
+
+var add1 = add.bind(add, 1)
+
+add1(3) // = 4
+
+10 Partial application (cont.)
++After ES6 introduced arrow functions, partial application has become +more popular +
+ +var add = x => y => x + y
+
+11 Currying
++Related to partial application, but more implicit and general +
+ ++Translates 1 function of arity n to n functions of arity 1 +
+ +function volume (w, d, h) {
+ return w * d * h
+}
+
+var vol = curry(volume)
+vol(10)(20)(30)
+// is strictly equivalent to
+volume(10, 20, 30)
+
+12 Easy Currying
++In order to make currying (and partial application) easier to use, +move the most important argument to a function to the end: +
+ +var badMap = (arr, fn) => arr.map(fn)
+var goodMap = (fn, arr) => arr.map(fn)
+var curriedBadMap = curry(badmap)
+var curriedGoodMap = curry(goodMap)
+
+var goodDoubleArray = goodMap(x => x * 2)
+var badDoubleArray = badMap(_, x => x * 2)
+
++The bad version requires the curry function to support a magic +placeholder argument and doesn't look as clean. +
+13 Practical Currying
++Currying is not automatic in JavaScript, as in other languages +
+ ++External tools aren't (so far) able to statically analyse curried +functions +
+ ++Solution: Don't expose curried functions +Instead, write functions as if currying were automatic +
+ ++If consumers want to curry, they can. If they don't, their editor or +language server will show them the arguments +
+14 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
+
function compose (f, g) {
+ return function (...args) {
+ return f(g(...args))
+ }
+}
+
+15 Functional composition (cont.)
+var plusOne = x => x + 1
+var timesTwo = x => x * 2
+
+var plusOneTimesTwo = compose(timesTwo, plusOne)
+var timesTwoPlusOne = compose(plusOne, timesTwo)
+
+nextDoubled(3) // = (3 + 1) * 2 = 8
+doubledPlusOne(3) // = (3 * 2) + 1 = 7
+
+16 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)
+
17 Point-free programming
++With currying and higher-order functions, we (often) don't need to declare function arguments +
+ +var modulo = a => b => b % a
+var eq = a => b => a === b
+
+var isEven = x => eq(0)(modulo(2)(x))
+var isEvenPointFree = compose(eq(0), modulo(2))
+
+18 Further Resources
+-
+
- Mostly adequate guide to FP (in javascript) +
- Ramda, a general-purpose FP library +
- Sanctuary, a JavaScript library for Haskellers +