Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The Joys of Functional Programming

The Joys of Functional Programming

The fun that can be had in functional programming, from someone who is not a functional programmer.

C01828b92e05aea326a6e2dbeb59f373?s=128

Stephen Mizell

February 09, 2015
Tweet

Transcript

  1. The Joys of Functional Programming Stephen Mizell

  2. First, Some Caveats 1. I do not do 100% functional

    programming 2. I will be showing examples in Javascript 3. I do not currently use functional reactive programming
  3. What is Functional Programming? 1. Imperative vs. Declarative 2. Persistent

    and Immutable Data 3. No Side Effects 4. Noun vs. Verb 5. First class and higher order functions 6. Recursive over iterative
  4. Common Functions 1. Map (transform to some) 2. Filter 3.

    Reduce
  5. Recursive vs. Iterative

  6. Iterative Factorial var num = 5, total = 1; if

    (num !== 0) { for (i = 1; i <= num; i++) { console.log(i); total = total * i; } } console.log(total);
  7. Recursive Factorial var num = 5; function factorial(n) { if

    (n === 0) return 1; return n * factorial(n - 1); } console.log(factorial(num));
  8. Imperative vs. Declarative Imperative you express how to do it,

    declarative you express what you want done
  9. Imperative var list = [1, 2, 3, 4, 5], total

    = 0; for (i = 0; i < list.length; i++) { total += list[i]; }
  10. Declarative (Part 1) var list = [1, 2, 3, 4,

    5]; var total = list.reduce(function(result, num) { return result + num; });
  11. Declarative (Part 2) var list = [1, 2, 3, 4,

    5]; function add(a, b) { return a + b; } var total = list.reduce(add);
  12. Declarative (Part 3) var list = [1, 2, 3, 4,

    5]; function add(a, b) { return a + b; } function sum(items) { return items.reduce(add); } var total = sum(list);
  13. Using a Functional Language Clojure (def items `(1 2 3

    4 5)) (reduce + items)
  14. One More Example!

  15. Here's Some Data var players = [ { totalPoints: 2031,

    games: 30 }, { totalPoints: 4268, games: 45 }, { totalPoints: 2235, games: 24 }, { totalPoints: 1221, games: 22 }, { totalPoints: 5420, games: 40 } ];
  16. Requirements 1. Get a list of the average points for

    each player 2. Get an average for all players who have played 30 or more games
  17. Imperative var playerAverages = [], allPoints = 0, allGames =

    0; for (i = 0; i < players.length; i++) { var average = players[i].totalPoints / players[i].games; playerAverages.push(average); if (players[i].games >= 30) { allPoints += players[i].totalPoints; allGames += players[i].games; } } var totalAverage = allPoints / allGames;
  18. Declarative (Part 1) var playerAverages = players.map(function(player) { return player.totalPoints

    / player.games; }); var players30Games = players.filter(function(player) { return player.games >= 30 }); var points = players30Games.map(function(player) { return player.totalPoints; }); var games = players30Games.map(function(player) { return player.games; }); var totalPoints = sum(points), totalGames = sum(games); totalAverage = totalPoints / totalGames;
  19. Declarative (Part 2) function pluck(items, prop) { return items.map(function(item) {

    return item[prop]; }); } function average(a, b) { return a / b; } var playerAverages = players.map(function(player) { return player.totalPoints / player.games; }); var players30Games = players.filter(function(player) { return player.games >= 30 }); var totalPoints = sum(pluck(players30Games, 'totalPoints')), totalGames = sum(pluck(players30Games, 'games')); totalAverage = average(totalPoints, totalGames);
  20. Currying Currying is the technique of translating the evaluation of

    a function that takes multiple arguments (or a tuple of arguments) into evaluating a sequence of functions, each with a single argument (partial application). –Wikipedia
  21. Currying function add(a) { return function(b) { return a +

    b; } } var add10 = add(10); console.log(add10(5)); // 15
  22. Currying (Better Example) var fullName = _.curry(function(first, middle, last) {

    return [first, middle, last].join(' '); }); var johnA = fullName('John', 'A.'); var johnASmith = johnA('Smith'); // John A. Smith
  23. Currying (From Player Data Example) // Uses a library called

    Ramda var players30Games = R.filter(R.pipe(R.get('games'), R.lte(30))); var totalPoints = R.pipe(players30Games, R.pluck('totalPoints'), R.sum); totalPoints(players)
  24. How is declarative helpful? 1. Testable, maintainable, evolvable code 2.

    Writing code at a higher level of abstraction 3. Through composition, it can lead to a very powerful way of thinking (like SQL)
  25. Persistent

  26. Persistent State 1. Values are immutable 2. A "change" in

    a value returns a new value (old is never thrown away) 3. These values persist (not necessarily on disk, but throughout time) 4. Big plus: fast!
  27. Crude Example A -> B -> C Sharing all of

    A Z -> A -> B -> C Sharing tail of A Y -> B -> C
  28. Persistence 1. Shared memory usage 2. No need to do

    deep clones of objects to avoid changing state 3. Allows for immutable data 4. Allows for understanding what has changed 5. Allows for no side effects
  29. Side Effects

  30. Side Effects var x = 10; function a() { x

    = 4; } console.log(x);
  31. Side Effects var x = 10; function a() { x

    = 4; } a(); console.log(x);
  32. Mutable Data

  33. Mutating Data x = 4; // ...later x = 10;

    y = x + 10;
  34. Mutating Data x = x + 1;

  35. Why is persistence and immutability good? 1. We've probably all

    spent hours chasing down bugs from side effects 2. Code that mutates data requires following steps through code to understand what it is doing 3. Mutating lots of code can be expensive
  36. Libraries for Javascript 1. Underscore.js and Lo-Dash.js provide some functions

    2. Ramda - Function-first library 3. Mori - Immutable data structures in Javascript 4. React.js and Immutable.js 5. ClojureScript
  37. Recap, why is this helpful? 1. Code is more declarative

    2. Promotes reusability and evolvability 3. Easier to write automated tests 4. Fewer bugs
  38. Bonus Functional Reactive Programming

  39. FRP There is no simple definition of this on the

    internet, so here are some qualities. 1. Deal with events in a functional way 2. Create streams of events rather than event listeners 3. Free of side effects
  40. Some Libraries 1. Bacon.js 2. Elm 3. RxJS

  41. Bacon.js function movieSearch(query) { if (query.length < 3) // show

    no results for queries of length < 3 return Bacon.once([]); return Bacon.fromPromise(queryMovie(query)); } var text = $('#input') .asEventStream('keydown') .debounce(300) .map(function(event) { return event.target.value; }) .skipDuplicates(); // Only react to latest, in case they are out of order var suggestions = text.flatMapLatest(movieSearch); text.awaiting(suggestions).onValue(function(x) { if (x) $('#results').html('Searching...'); }); suggestions.onValue(function(results) { $('#results').html($.map(results, showMovie)); });