Programación funcional
    con Javascript
             Leo Soto M.

    Lecture & Beer 2010, Continuum.
¿Programación funcional?
Scheme? ML? F#? Haskell?
Dos principios
Principio 1:

Olvida las variables. Existen valores y ya.
Principio 1:

Olvida las variables. Existen valores y ya.

¡Como en matemáticas!
variables == bugs
x = x + 1
x = x + 1 // -x
x = x + 1 // -x

x - x = x - x + 1
x = x + 1 // -x

x - x = x - x + 1

0    = 1
x = x + 1 // -x

x - x = x - x + 1

0     = 1
WTF
¡Pero esta charla no trata sobre ese principio!
> var foo = “estamos jodidos”
Principio 1I:

Las funciones son valores
Principio 1I:

Las funciones son valores primitivos
> var miVariable = 1
> var miVariable = 1
> var otraVariable = miVariable
> var miVariable = 1
> var otraVariable = miVariable
> typeof(miVariable)
number
> function miFuncion() { return 1 }
> typeof(miFuncion)
function
> function miFuncion() { return 1 }
> typeof(miFuncion)
function

> var otraFuncion = miFuncion;
> typeof(otraFuncion)
fun...
> function miFuncion() { return 1 }
> typeof(miFuncion)
function

> var otraFuncion = miFuncion;
> typeof(otraFuncion)
fun...
Sintaxis equivalente:
> function f(x, y) { ... }
> var f = function(x, y) { ... }
Higher order functions:

Funciones que reciben funciones
function time(f) {
  start = new Date().getTime();
  f()
  end = new Date().getTime();
  print(“Milliseconds: ” +
        ...
time(function() {
   var x = 1;
   for (var i = 2; i < 1000; i++) {
       x = x * i;
   }
})
Higher order functions:

Funciones que retornan funciones
$(“#edad”).blur(
   function() {
     validarRango(this, 18, 65);
   }
);
$(“#edad”).blur(
   validadorRango(18, 65)
);
function validadorRango(a, b) {
  return function() {
    var v = $(this).val();
    if (v < a || v > b) {
      alert(“Fu...
¡Closures!
function validadorRango(a, b) {
  return function() {
    var v = $(this).val();
    if (v < a || v > b) {
      alert(“Fu...
function validadorRango(a, b) {
  return function() {
    var v = $(this).val();
    if (v < a || v > b) {
      alert(“Fu...
function validadorRango(a, b) {
  return function() {
    var v = $(this).val();
    if (v < a || v > b) {
      alert(“Fu...
Es como escribir macros, o plantillas
function validadorRango(a, b) {
  return function() {
    var v = $(this).val();
    if (v < a || v > b) {
      alert(“Fu...
Primitivas funcionales:

  map, filter, reduce,
       any, all,
        partial
map
> function double(x) { return x * x }
> map([1, 2, 3], double)
[2, 4, 6]
function map(array, f) {
  var r = [];
  for (var i in array) {
    r.push(f(array[i]);
  }
  return r;
}
reduce
> function sum(x, y) { return x + y }
> function mul(x, y) { return x * y }
> reduce([1, 2, 3, 4], 0, sum)
10
> reduce([1,...
function reduce(array, inicial, f) {
  var r = inicial
  for (var i in array) {
    r = f(r, array[i]);
  }
  return r;
}
filter
> function par(x) {return x % 2 == 0}
> filter([1,2,3,4,5], par)
[2, 4]
function filter(array, f) {
  var r = [];
  for (var i in array) {
    if (f(array[i])) {
      r.push(array[i]);
    }
  ...
any
> function par(x) {return x % 2 == 0}
> any([1,2,3,4,5], par)
true
> any([1,3,5], par)
false
function any(array, f) {
  for (var i in array) {
    if (f(array[i])) {
      return true;
    }
  }
  return false;
}
all
> function par(x) {return x % 2 == 0}
> all([1,2,3,4,5], par)
false
> all([2,4,6], par)
true
function all(array, f) {
  for (var i in array) {
    if (!f(array[i])) {
      return false;
    }
  }
  return true;
}
function all(array, f) {
  return !any(array, function(x) {
    return !f(x)
  }
}
partial
> function mul(x, y) { return x * y }
> var double = partial(mul, 2)
> double(10)
20
function partial(f) {
  var fixedArgs = arguments.splice(
     1, arguments.length - 1);
  return function() {
     return...
Ejemplos
supers = filter(users, function(u) {
  return u.superuser;
}
names = map(supers, function(u) {
  return u.fullName;
});
function getprop(x) {
  return function(o) {
    return o[x];
  }
}
supers = filter(users,
                getprop(“superuser”))
names = map(supers,
            getprop(“fullName”))
filter(leagues, function(league) {
  return any(league.users,
             getprop(“unapproved”));
});
reduce(
  map(users, getprop(“age”)),
  -1,
  Math.max
)
Familiar feeling?



map(usuarios, f)        =~ SELECT f(usuario)
filter(usuarios, f)      =~ WHERE f(usuario)
any(usuarios...
var phones = []
for (var i in users) {
  var user = users[i];
  var userPhones = [];
  if (user.phones[0]) {
    userPhone...
function first(n, array) {
  var r = [];
  for (var i = 0;
       i < Math.min(array.length, n);
       i++) {
    r.push(...
var phones = []
for (var i in users) {
  phones.push(
     first(2, users.phones)
  );
}
function compose(f, g) {
  return function(x) {
    return f(g(x));
  }
}
map(users,
    compose(partial(first, 2),
            getprop(“phones”)))
map(users, function(u) {
    return first(2, u.phones);
});
Implementaciones
Javascript 1.6 (Mozilla)


                                    array.map,
                                  array.filter
 ...
JQuery




      $.map,
  $(“.foo”).map
$(“.foo”).filter
Underscore
 http://documentcloud.github.com/underscore/

_.map, _.reduce, _.detect, _.all, _.any,
              _.sortBy, ...
¡Eso!
¿Preguntas?
Upcoming SlideShare
Loading in...5
×

Javascript funcional

1,807
-1

Published on

0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,807
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
28
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide










































































  • Javascript funcional

    1. 1. Programación funcional con Javascript Leo Soto M. Lecture & Beer 2010, Continuum.
    2. 2. ¿Programación funcional?
    3. 3. Scheme? ML? F#? Haskell?
    4. 4. Dos principios
    5. 5. Principio 1: Olvida las variables. Existen valores y ya.
    6. 6. Principio 1: Olvida las variables. Existen valores y ya. ¡Como en matemáticas!
    7. 7. variables == bugs
    8. 8. x = x + 1
    9. 9. x = x + 1 // -x
    10. 10. x = x + 1 // -x x - x = x - x + 1
    11. 11. x = x + 1 // -x x - x = x - x + 1 0 = 1
    12. 12. x = x + 1 // -x x - x = x - x + 1 0 = 1 WTF
    13. 13. ¡Pero esta charla no trata sobre ese principio!
    14. 14. > var foo = “estamos jodidos”
    15. 15. Principio 1I: Las funciones son valores
    16. 16. Principio 1I: Las funciones son valores primitivos
    17. 17. > var miVariable = 1
    18. 18. > var miVariable = 1 > var otraVariable = miVariable
    19. 19. > var miVariable = 1 > var otraVariable = miVariable > typeof(miVariable) number
    20. 20. > function miFuncion() { return 1 } > typeof(miFuncion) function
    21. 21. > function miFuncion() { return 1 } > typeof(miFuncion) function > var otraFuncion = miFuncion; > typeof(otraFuncion) function
    22. 22. > function miFuncion() { return 1 } > typeof(miFuncion) function > var otraFuncion = miFuncion; > typeof(otraFuncion) function > typeof(otraFuncion()) number
    23. 23. Sintaxis equivalente:
    24. 24. > function f(x, y) { ... } > var f = function(x, y) { ... }
    25. 25. Higher order functions: Funciones que reciben funciones
    26. 26. function time(f) { start = new Date().getTime(); f() end = new Date().getTime(); print(“Milliseconds: ” + (start - end)); }
    27. 27. time(function() { var x = 1; for (var i = 2; i < 1000; i++) { x = x * i; } })
    28. 28. Higher order functions: Funciones que retornan funciones
    29. 29. $(“#edad”).blur( function() { validarRango(this, 18, 65); } );
    30. 30. $(“#edad”).blur( validadorRango(18, 65) );
    31. 31. function validadorRango(a, b) { return function() { var v = $(this).val(); if (v < a || v > b) { alert(“Fuera de rango”); } } }
    32. 32. ¡Closures!
    33. 33. function validadorRango(a, b) { return function() { var v = $(this).val(); if (v < a || v > b) { alert(“Fuera de rango”); } } }
    34. 34. function validadorRango(a, b) { return function() { var v = $(this).val(); if (v < a || v > b) { alert(“Fuera de rango”); } } } ¡No se ejecuta inmediatamente!
    35. 35. function validadorRango(a, b) { return function() { var v = $(this).val(); if (v < a || v > b) { alert(“Fuera de rango”); } } } ¡No se ejecuta inmediatamente! ¡Pero puede acceder a valores de “afuera”!
    36. 36. Es como escribir macros, o plantillas
    37. 37. function validadorRango(a, b) { return function() { var v = $(this).val(); if (v < a || v > b) { alert(“Fuera de rango”); } } }
    38. 38. Primitivas funcionales: map, filter, reduce, any, all, partial
    39. 39. map
    40. 40. > function double(x) { return x * x } > map([1, 2, 3], double) [2, 4, 6]
    41. 41. function map(array, f) { var r = []; for (var i in array) { r.push(f(array[i]); } return r; }
    42. 42. reduce
    43. 43. > function sum(x, y) { return x + y } > function mul(x, y) { return x * y } > reduce([1, 2, 3, 4], 0, sum) 10 > reduce([1, 2, 3, 4], 1, mul) 24
    44. 44. function reduce(array, inicial, f) { var r = inicial for (var i in array) { r = f(r, array[i]); } return r; }
    45. 45. filter
    46. 46. > function par(x) {return x % 2 == 0} > filter([1,2,3,4,5], par) [2, 4]
    47. 47. function filter(array, f) { var r = []; for (var i in array) { if (f(array[i])) { r.push(array[i]); } } return r; }
    48. 48. any
    49. 49. > function par(x) {return x % 2 == 0} > any([1,2,3,4,5], par) true > any([1,3,5], par) false
    50. 50. function any(array, f) { for (var i in array) { if (f(array[i])) { return true; } } return false; }
    51. 51. all
    52. 52. > function par(x) {return x % 2 == 0} > all([1,2,3,4,5], par) false > all([2,4,6], par) true
    53. 53. function all(array, f) { for (var i in array) { if (!f(array[i])) { return false; } } return true; }
    54. 54. function all(array, f) { return !any(array, function(x) { return !f(x) } }
    55. 55. partial
    56. 56. > function mul(x, y) { return x * y } > var double = partial(mul, 2) > double(10) 20
    57. 57. function partial(f) { var fixedArgs = arguments.splice( 1, arguments.length - 1); return function() { return f.apply( this, fixedArgs.concat(arguments) ); }; }
    58. 58. Ejemplos
    59. 59. supers = filter(users, function(u) { return u.superuser; } names = map(supers, function(u) { return u.fullName; });
    60. 60. function getprop(x) { return function(o) { return o[x]; } }
    61. 61. supers = filter(users, getprop(“superuser”)) names = map(supers, getprop(“fullName”))
    62. 62. filter(leagues, function(league) { return any(league.users, getprop(“unapproved”)); });
    63. 63. reduce( map(users, getprop(“age”)), -1, Math.max )
    64. 64. Familiar feeling? map(usuarios, f) =~ SELECT f(usuario) filter(usuarios, f) =~ WHERE f(usuario) any(usuarios, f) =~ SOME(f(usuario)) all(usuarios, f) =~ ALL(f(usuario)) reduce(usuarios, ...) =~ MAX/MIN/AVG...
    65. 65. var phones = [] for (var i in users) { var user = users[i]; var userPhones = []; if (user.phones[0]) { userPhones.push(user.phones[0]); } if (user.phones[1]) { userPhones.push(user.phones[1]); } phones.push(userPhones); }
    66. 66. function first(n, array) { var r = []; for (var i = 0; i < Math.min(array.length, n); i++) { r.push(array[i]); } return r; }
    67. 67. var phones = [] for (var i in users) { phones.push( first(2, users.phones) ); }
    68. 68. function compose(f, g) { return function(x) { return f(g(x)); } }
    69. 69. map(users, compose(partial(first, 2), getprop(“phones”)))
    70. 70. map(users, function(u) { return first(2, u.phones); });
    71. 71. Implementaciones
    72. 72. Javascript 1.6 (Mozilla) array.map, array.filter array.reduce* array.some array.every *Introducido en Javascript 1.8
    73. 73. JQuery $.map, $(“.foo”).map $(“.foo”).filter
    74. 74. Underscore http://documentcloud.github.com/underscore/ _.map, _.reduce, _.detect, _.all, _.any, _.sortBy, ... _.first, _.rest, _.compact, _.flatten, _.uniq, _.zip, _.intersect, ... _.invoke, _.pluck, _.tap, ... _.keys, _.values, ... _.compose, _.bind, _.memoize
    75. 75. ¡Eso!
    76. 76. ¿Preguntas?
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×