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 -