Functional Programming Fundamentals in JS & PHP

5f52c5d9bba5225dcd3552699923ba4a?s=47 krisjordan
January 24, 2012

Functional Programming Fundamentals in JS & PHP

Slide deck from talk given at Triangle JS / PHP / MySQL meetup.

5f52c5d9bba5225dcd3552699923ba4a?s=128

krisjordan

January 24, 2012
Tweet

Transcript

  1. Learn Functional Programming (by implementing a SQL DSL) in JavaScript

    and PHP @KrisJordan Tuesday, January 24, 12
  2. Who am I? • Kris Jordan • Founder at New

    Media Campaigns • Ping me via... • Twitter: @KrisJordan • GitHub: KrisJordan • Email: KrisJordan@gmail.com • KrisJodan.com @KrisJordan Tuesday, January 24, 12
  3. Main Street, Carrboro N E W M E D I

    A C A M P A I G N S Tuesday, January 24, 12
  4. Objectives 1. Grok functional programming fundamentals 2. Familiarity with underscore.(js|php)

    3. Transfer SQL knowledge to FP @KrisJordan Tuesday, January 24, 12
  5. Why should you care about Functional Programming? @KrisJordan Tuesday, January

    24, 12
  6. $(“p”).each(function(){ $(this).wrap(“<marquee/>”); }); 1. We already use functional programming techniques

    @KrisJordan Tuesday, January 24, 12
  7. 2. Our code consumes data. @KrisJordan Tuesday, January 24, 12

  8. with fewer bugs and think differently 3. You’ll write less

    code about programming. @KrisJordan Tuesday, January 24, 12
  9. So, what is Functional Programming? @KrisJordan Tuesday, January 24, 12

  10. λ Church @KrisJordan Tuesday, January 24, 12

  11. (McCarthy) @KrisJordan Tuesday, January 24, 12

  12. Functions are data. @KrisJordan Tuesday, January 24, 12

  13. // JavaScript here <?php // php here Title here. Tuesday,

    January 24, 12
  14. Functions are data. var logMessage = function(){ console.log(“Hello, world.”); };

    logMessage(); $logMessage = function(){ echo(“Hello, world.”); }; $logMessage(); Tuesday, January 24, 12
  15. Functions can be passed to Executor functions. var executor =

    function(aFunction){ aFunction(); } executor(logMessage); $executor = function($aFunction){ $aFunction(); }; $executor($logMessage); Tuesday, January 24, 12
  16. jQuery’s API is awesome thanks to Executor functions. $(‘h1’).click(function(){ console.log(“Hello,

    world”); }); @KrisJordan $(“p”).each(function(){ $(this).wrap(“<marquee/>”); }); Tuesday, January 24, 12
  17. underscore.(js|php) 60-some classic functions @KrisJordan Tuesday, January 24, 12

  18. @KrisJordan Tuesday, January 24, 12

  19. map( 3 2 1 , function(item){ return item * item;

    } ); @KrisJordan Tuesday, January 24, 12
  20. map( 3 2 1 , function(item){ return item * item;

    } ); @KrisJordan Tuesday, January 24, 12
  21. map( 3 2 1 , function(item){ return item * item;

    } ); 9 @KrisJordan Tuesday, January 24, 12
  22. map( 3 2 1 , function(item){ return item * item;

    } ); 9 4 @KrisJordan Tuesday, January 24, 12
  23. map( 3 2 1 , function(item){ return item * item;

    } ); 9 4 1 @KrisJordan Tuesday, January 24, 12
  24. map( 3 2 1 , function(item){ return item * item;

    } ); 9 4 1 return to caller @KrisJordan Tuesday, January 24, 12
  25. map implemented var map = function(collection, fn) { var rv

    = []; for(var i = 0; i < collection.length; i++){ var item = collection[i]; rv.push(fn(item)); } return rv; } $map = function($collection, $fn) { $rv = array(); for($i = 0; $i < count($collection); i++){ $item = $collection[$i]; $rv[] = $fn($item); } return $rv; } Tuesday, January 24, 12
  26. filter( 3 2 1 ,function(item){ return item % 2 ===

    1; } ); @KrisJordan Tuesday, January 24, 12
  27. filter( 3 2 1 ,function(item){ return item % 2 ===

    1; } ); true? yes 3 @KrisJordan Tuesday, January 24, 12
  28. filter( 3 2 1 ,function(item){ return item % 2 ===

    1; } ); true? no! 3 @KrisJordan Tuesday, January 24, 12
  29. filter( 3 2 1 ,function(item){ return item % 2 ===

    1; } ); true? yes 3 1 @KrisJordan Tuesday, January 24, 12
  30. filter( 3 2 1 ,function(item){ return item % 2 ===

    1; } ); 3 1 return to caller @KrisJordan Tuesday, January 24, 12
  31. pluralFn( item item item , singularFn ); @KrisJordan Tuesday, January

    24, 12
  32. underscore.(js|php) 60-some classic functions @KrisJordan Tuesday, January 24, 12

  33. pluralFn( item item item , singularFn ); executor how can

    we do better here? @KrisJordan Tuesday, January 24, 12
  34. Executor Function jQuery(‘h1’).click( ); @KrisJordan Tuesday, January 24, 12

  35. Executor Function Anonymous Function $(‘h1’).click(function(){ $(this).toggleClass(“selected”); }); @KrisJordan Tuesday, January

    24, 12
  36. Executor Function Anonymous Function Function Variable var toggleSelected = function(){

    $(this).toggleClass(“selected”); }; $(‘h1’).click(toggleSelected); @KrisJordan Tuesday, January 24, 12
  37. Executor Function Anonymous Function Function Variable $(‘h1’).click(toggleClass(“selected”)); @KrisJordan Tuesday, January

    24, 12
  38. Executor Function Anonymous Function Function Variable Generator Function var toggleClass

    = function(klass){ return function(){ $(this).toggleClass(klass); }; }; $(‘h1’).click(toggleClass(“selected”)); Tuesday, January 24, 12
  39. Functions can be returned by Generator functions. var genMessageFn =

    function(msg) { return function(){console.log(msg);}; }; jQuery(‘h1’).click(genMessageFn(“Hi!”)); $genMessageFn = function($msg) { return function()use($msg){echo($msg);}; }; $executor($genMessageFn(“Hi!”)); Tuesday, January 24, 12
  40. Something smells fishy, var genMessageFn = function(msg) { return function(){console.log(msg);};

    }; $(‘h1’).click(genMessageFn(“Hi!”)); $genMessageFn = function(msg) { return function()use($msg){echo($msg);}; }; $executor($genMessageFn(“Hi!”)); doesn’t `msg` pop off the stack? Tuesday, January 24, 12
  41. Functions can be closures. They “trap” var refs into a

    fn’s scope. JS closures are implicit. PHP closures are explicit. function() use($msg) {...} Tuesday, January 24, 12
  42. Executor Function Anonymous Function var toggleClass = function(klass){ return function(){

    $(this).toggleClass(klass); }; }; $(‘h1’).click(toggleClass(“selected”)); Function Variable Generator Function “Trapped” in Scope by Closure Tuesday, January 24, 12
  43. Closures in OOP terms: native, minimal Command pattern class MsgCommand

    { private $_msg; function __construct($msg) { $this->$_msg = $msg; } function exec() { echo $this->_msg; } } $cmd = new MsgCommand(“OOP”); $cmd->exec(); $msgCommand = function($msg) { return function()use($msg) { echo $msg; }; }; $cmd = $msgCommand(“FP”); $cmd(); OOP FP @KrisJordan Tuesday, January 24, 12
  44. Refactor to Generator @KrisJordan Anonymous Function Function Variable Generator Function

    refactor for reuse refactor for parameters Tuesday, January 24, 12
  45. var toggleClassSelected = function(){ $(this).toggleClass(“selected”); }; $(‘h1’).click(toggleClassSelected); $(‘h1’).click(function(){ $(this).toggleClass(“selected”); });

    var toggleClass = function(klass){ return function(){ $(this).toggleClass(klass); }; }; $(‘h1’).click(toggleClass(“selected”)); Anon Function Function Variable Generator Function refactor for reuse refactor for parameters refactor for reuse refactor for parameters Tuesday, January 24, 12
  46. Let’s Implement a SQL DSL SELECT p.first, p.last, p.games, p.points

    FROM players AS p WHERE p.games = 19 ORDER BY p.last @KrisJordan Tuesday, January 24, 12
  47. Let’s Implement a SQL DSL SELECT p.first, p.last, p.games, p.points

    FROM players AS p WHERE p.games = 19 ORDER BY p.last _.filter _.sortBy _.map _.map @KrisJordan Tuesday, January 24, 12
  48. Our Goal select([“p.first”, “p.last”, “p.games”, “p.points”], orderBy(“p.last”, where(equals(c(“p.games”),19), from(“players”,”p”,tables)))); @KrisJordan

    Tuesday, January 24, 12
  49. Live coding. Tuesday, January 24, 12

  50. Recap • Functions are data • Closures “trap” variable references

    in scope, useful for generating functions • Write singular function generators, leverage with plural executor functions • Underscore provides great executor functions for processing data @KrisJordan Tuesday, January 24, 12
  51. Tuesday, January 24, 12

  52. any( 3 2 1 ,function(item){ return item % 2 ===

    1; } ); Tuesday, January 24, 12
  53. any( 3 2 1 ,function(item){ return item % 2 ===

    1; } ); true? yes true Tuesday, January 24, 12
  54. any( 3 2 1 ,function(item){ return item % 2 ===

    1; } ); true? yes true return to caller Tuesday, January 24, 12
  55. reject( 3 2 1 ,function(item){ return item % 2 ===

    1; } ); Tuesday, January 24, 12
  56. reject( 3 2 1 ,function(item){ return item % 2 ===

    1; } ); 2 return to caller Tuesday, January 24, 12
  57. reduce( 3 2 1 , function(memo,item){ return memo + item;

    } ); , 0 Tuesday, January 24, 12
  58. reduce( 3 2 1 , function(memo,item){ return memo + item;

    } ); 0 , 0 memo Tuesday, January 24, 12
  59. reduce( 3 2 1 , ); 0 , 0 memo

    function(memo,item){ return 0+3; } Tuesday, January 24, 12
  60. reduce( 3 2 1 , ); 3 , 0 memo

    function(memo,item){ return 0+3; } Tuesday, January 24, 12
  61. reduce( 3 2 1 , ); 3 , 0 memo

    function(memo,item){ return 3+2; } Tuesday, January 24, 12
  62. reduce( 3 2 1 , ); 5 , 0 memo

    function(memo,item){ return 3+2; } Tuesday, January 24, 12
  63. reduce( 3 2 1 , ); 5 , 0 memo

    function(memo,item){ return 5+1; } Tuesday, January 24, 12
  64. reduce( 3 2 1 , ); 6 , 0 memo

    function(memo,item){ return 5+1; } Tuesday, January 24, 12
  65. reduce( 3 2 1 , function(memo,item){ return memo + item;

    } ); 6 , 0 memo return to caller Tuesday, January 24, 12