diff options
Diffstat (limited to 'static/talks/fp-js/index.org')
-rw-r--r-- | static/talks/fp-js/index.org | 226 |
1 files changed, 0 insertions, 226 deletions
diff --git a/static/talks/fp-js/index.org b/static/talks/fp-js/index.org deleted file mode 100644 index 8a4bf6c..0000000 --- a/static/talks/fp-js/index.org +++ /dev/null @@ -1,226 +0,0 @@ -#+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 |