From e5cb8f1ef60c36d29d66bf8dbb25365423b9b3c8 Mon Sep 17 00:00:00 2001 From: Alan Pearce Date: Tue, 24 Oct 2017 12:04:46 +0200 Subject: Add fp-js talk --- static/talks/fp-js/slides.html | 431 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 431 insertions(+) create mode 100644 static/talks/fp-js/slides.html (limited to 'static/talks/fp-js/slides.html') diff --git a/static/talks/fp-js/slides.html b/static/talks/fp-js/slides.html new file mode 100644 index 0000000..e90650c --- /dev/null +++ b/static/talks/fp-js/slides.html @@ -0,0 +1,431 @@ + + + + + + +Functional Programming in JavaScript + + + + + + + + + + + + + + + + +
+
+
+ + + + +
+
+
+

Functional Programming in JavaScript

+

+

Alan Pearce

+

alan@alanpearce.eu

+

+
+
+

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

+
+ +
+
+ + +
+ + -- cgit 1.4.1