domingo, 8 de enero de 2012

Lazy evaluation - Evaluacion perezosa (Javascript para programadores funcionales - Parte 2 )

x Antes de adentrarne en esta idea, primero pensemos un poco en que es la evaluación.

 ¿Qué es la evaluación?
  Es la ejecución o reducción de un computo a su forma mas simple. Teniendo por computo cualquier cosa suceptible a ser computada: funciones, aplicacion de operadores, expresiones booleanas, etc.

  Análisis

  Hay varios aspectos en el análisis de la forma de evaluación. El tema de este post es el computo en el tiempo, o sea, el momento en que se da el computo.

   En el caso de eager evaluation la evaluacion se hace lo antes posible, en el caso de lazy evaluation se deja para el momento en que realmente es necesaria.

  Uno de los casos emblematicos (no reproducibles en javascript) es el de las listas infinitas. Haskell por ejemplo permite que uno defina una lista infinita:


   x = [1..]



  Esto es posible por que la lista se va generando on demand a diferencia de la mayoria de los lenguajes, donde antes de usar una lista, esta tiene que estar creada. (Este aspecto puede ser llevado mas lejos, pero eso esta out-of-scope).

  Un ejemplo mas mundano es el de la necesidad de datos, por ejemplo cuando uno necesita datos para poder ejecutar una funcion y estos datos son obtenidos de otra funcion, uno tiene que ejecutar las segundas para poder aplicar la primera.


   funcionQueNecesitaDatos(fndata1(), fndata2(),..., fndataN());


En el caso de javascript, un debug nos diria que primero se ejecuta fndata1, despues la 2 y asi hasta llegar a la N, una vez resueltos los parametros, se ejecuta funcionQueNecesitaDatos.


  En haskell, por ejemplo, el resultado de una funcion no se termina de evaluar hasta que es realmente necesario, o sea, hasta que funcionQueNecesitaDatos usa el parametro. Supongamos una funcionQueNecesitaDatos de la forma

   funcionQueNecesitaDatos (a,b,c){
      if(a) return b;
      else return c;
   }


En el esquema de eager evaluation se ejecutan las cuatro funciones, en el esquema de lazy evaluation solo se ejecutan tres. Si a eso sumamos que todo en haskell es una funcion, inclusive las expresiones (3 > 2) y que tambien se evaluan on demand vemos que no se ejecuta absolutamente nada que sea innecesario y todo se obtiene al momento en que se necesita. Ese es el poder del esquema lazy evaluation.

Claramente en javascript tampoco podemos llegar a ese nivel de granularidad, es una cuestion de la concepcion del lenguaje. Pero, pero, peeero, podemos re pensar un poco nuestro código para que tienda a ese lado, lo que nos lleva a que las funciones son datos :)


Las funciones son datos y pueden ser pasadas por parámetro


function funcionQueNecesitaDatos (expresion, then, otherwise) {
     if(expresion()) return then();
     else return otherwise();
}







funcionQueNecesitaDatos(fnData1,fnData2, fnData3)


Como se puede ver en este caso, las funciones llegan por parametro y se ejecutan segun necesidad.

En este esquema tenemos la dificultad de que las funciones debieran ser todas invocables sin parámetros para que no sea una gran complicación. 

En el post de highorder functions voy a mostrar un humilde hadouken para pasar este problemilla.







Corolario


Cuando tenemos código mas caro de ejecutar que la creacion de una función, podemos asegurarnos que se ejecute solo cuando sea necesario pasando funciones por parametro o buscando hooks que nos permitan estirar el momento de evaluación el mayor tiempo posible para asegurarnos que sea realmente necesaria su ejecución.

Esto nos da en retribución un código varios ordenes mas eficiente.


Como se lo contás a tu vieja?

A ella le decís que eager evaluation sería limpiar el cuarto estando ella de vacaciones, mientras que lazy evaluation es ordenar el cáos justo antes de que ella llegue.

No hay comentarios:

Publicar un comentario