jueves, 4 de junio de 2009

Funciones lambda o anonimas

Ahora que ya comprendemos el concepto de closures, podremos apreciar con mayor amplitud el verdadero poder de las funciones lambda o anonimas. Pero primero lo primero, porque se llaman lambda?.
Las funciones anonimas en programación deben el nombre de lambda, a la teoría matemática del Calculo Lambda inventada por Alonzo Church y Stephen Kleen (que no es el creador de la botella, ese es Klein) Teoría que sin duda esta fuera del alcance del entendimiento del humano medio, asi que si la comprendes, bien por ti.
Bien, ahora para que son utiles las funciones lambda?, de que sirve no ponerle nombre a una función?. Las utilidaded de las funciones lambda son casi infinitas pero intentaré mostrarles aquí las que yo considero son las más importantes.
Las posibilidad de usar funciones anonimas va de la mano con otros conceptos importantes de Javascript, como :
  • Todo es un objeto: (incluidas las funciones), esto me permite asignar funciones a variables, y hacer referencia a ellas utilizando la variable, además me permite pasar funciones como parametros a otras funciones, y obtener funciones como resultados de la ejecución de una función.
  • Closures: Gracias a las Closures tenemos la ventaja de poder enlazar nuestras funciones con variables de otros entornos de ejecución, algo que veremos es más que util a la hora de trabajar con interfaces web.
  • Objetos dinamicos: A la hora de modificar el comportamiento de un objeto en particular, podemos definir una funcion y asignarla inmediatamente a un método de un objeto, sobreescribiendo su comportamiento inicial, o extendiendo su interfaz para agregar comportamiento nuevo.
bueno ahora un poco de codigo:


//funcion lambda asignada a una variable
var sumar = function (a,b){
return a+b;
}
alert(sumar(1,2));
// es lo mismo que decir
function sumar (a,b){
return a+b;
}


ahora supongamos que tenemos una funcion que busca el más grande de todos los numeros en un array

var masGrande = function (arr){
var mayor=0;
var len = arr.length;
for(var i=0;i<>mayor){
mayor=arr[i];
}
}
return mayor;
}

var intArr = [1,2,3,4,5,6,7,8];
alert(masGrande(intArr));

ahora que sucede si queremos comparar por ejemplo un array de objetos personas, donde cada persona tiene un miembro edad con el valor de su edad. veamos como reescribiriamos la función

var masGrande = function (arrP){
var mayor=0;
var len = arr.length;
for(var i=0;i<>mayor.edad){
mayor=arr[i];
}
}
return mayor;
}
var personasArr = [{edad:2},{edad:2},{edad:2},{edad:2},{edad:2},{edad:2},{edad:2}];
alert(masGrande(personasArr));


Pero este codigo es solamente util para encontrar la mayor "persona", y no sirve para ningun otro tipo de objeto (aunque a decir verdad si los objetos del array poseen un miembro edad es suficiente).
Como podríamos escribir un algoritmo que aisle el comportamiento de buscar un mayor sin importar de los objetos que estemos comparando.
Bueno gracias a las funciones anonimas podemos.

//si analizamos los ejemplos anteriores podemos ver que lo unico que
//cambia es el momento de comparar si un objeto es mayor o no
//entonces que sucede si
var masGrande = function (arr, esMayor){
// en el parametro comparar recibiremos una funcion que compare dos objetos y nos
// pueda decir cual es el mayor.
var mayor=0;
var len = arr.length;
for(var i=0;i< mayor="arr[i];" personasarr =" [{edad:2},{edad:2},{edad:2},{edad:2},{edad:2},{edad:2},{edad:2}];">b.edad){
return true;
}else{
return false;
}
}));

//podemos buscar el mayor número
var intArr = [1,2,3,4,5,6,7,8];
alert(masGrande(intArr,function(a,b){
if(a>b){
return true;
}else{
return false;
}
}));

//podemos buscar el mayor de objetos con estructuras complicadas
var objArr = [{edad:20,fuerza:40},{edad:30,fuerza:50},{edad:10,fuerza:23},{edad:21,fuerza:40}];
alert(masGrande(objArr,function(a,b){
if((50-a.edad)*a.fuerza>(50-b.edad)*b.fuerza){
return true;
}else{
return false;
}
}));


Como vemos hemos logrado aislar el comportamiento de buscar un mayor sin importar los objetos que estemos comparando.

Ahora veamos un ejemplo simple para modificar el comportamiento de un objeto

var perro=function(){};

perro.prototype={
comer: function(){
alert('comiendo con el hocico');
}
};

var persona = new perro;
persona.comer=function(){
alert('comiendo con la boca');
};

es muy sencillo entender la utilidad de este tipo de estructuras luego de observar estos ejemplos
(los ejemplos no han sido probado, si al probarlos encontrases algun error por favor comunicamelo e intenta encontrar la solucion)

10 comentarios:

  1. Otro ejemplo que a mi me parece precioso tomado de Paul Graham:

    function make-adder (x) {
    return function (y) {return x+y;}
    }

    var add5=make-adder (5);
    alert (add5(8)); // 13

    ResponderEliminar
  2. var masGrande = function (arr){
    var mayor=0;
    var len = arr.length;
    for(var i=0;i<>mayor){
    mayor=arr[i];
    }
    }
    return mayor;
    }

    var intArr = [1,2,3,4,5,6,7,8];
    alert(masGrande(intArr));
    //esta funcion no funciona

    ResponderEliminar
    Respuestas
    1. Yo lo hice de otra forma espero les sirva n.n (Lo probe con Node.js y funciono bien)


      Array.prototype.myCase=function(){
      var mayor = 0;
      for(var i = 0; i actual) {
      // Nothing to do
      }
      else { mayor = actual; }

      }
      console.log("El mayor numreo es "+mayor);
      }


      var foo = [{a:1},{a:2},{a:3},{a:2},{a:2},{a:2},{a:2},{a:4},{a:5},{a:2},{a:1},{a:10},{a:0},{a:11}];


      foo.myCase();

      Eliminar
  3. //Así funciona

    var masGrande = function (arr){
    var mayor=0;
    var len = arr.length;
    for(var i=0;i<len; i++){
    mayor=arr[i];
    }
    return mayor;
    }

    var intArr = [1,2,3,4,5,6,7,8];
    alert(masGrande(intArr));

    ResponderEliminar
  4. muy buena manera de explicar las funciones lambda felicidades
    las prodrian explicar en c#
    Gracias

    ResponderEliminar
  5. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  6. //Así Tambien funciona

    Array.prototype.masGrande = function(){

    var mayor=0;
    var len = this.length;
    for(var i=0;i<len; i++){
    mayor=this[i];
    }
    return mayor;


    }
    var intArr = [1,2,3,4,5,6,7,8];
    alert(intArr.masGrande());

    ResponderEliminar
  7. Buen contenido, pero el fondo negro mata la vista

    ResponderEliminar