Mostrando entradas con la etiqueta tu vieja. Mostrar todas las entradas
Mostrando entradas con la etiqueta tu vieja. Mostrar todas las entradas

domingo, 8 de enero de 2012

highorder functions - Funciones de orden superior. (Javascript para programadores funcionales parte 3)

Ya en el artículo de lazy evaluation vimos que es copado pasar funciones por parametro para evitar ejecutar código antes de tiempo.

   High-order function es como se llama a las funciones que reciben funciones por parametro.

   A diferencia del artículo de lazy evaluation, las funciones de esta categoría son funciones que reciben criterios por parametro.

Qué es un criterio? 

Uhm, bueno, hay varias formas de criterio, pero creo que puedo generalizarlos en dos, criterio de consulta y criterio de ejecución. Un criterio de consulta es un computo que me permite saber algo de la ejecución. Un criterio de ejecución es un computo que me permite realizar una acción.

Un caso clarisimo es el if como funcion:

function ifFn (expression, ifTrue, ifFalse) {
  if(expression) ifTrue();
  else ifFalse();
}


Donde expression es un criterio de consulta, que nos dice si sucedio algo y ifTrue / ifFalse son unidades computables.

En este caso, la funcion de orden superior es ifFn, que define un comportamiento general que se termina de definir con las funciones que recibe por parametro.

Esta misma idea puede ser llevada a varios ambitos, sobre todo algoritmicos.


Cuantas veces hemos definido algoritmos identicos en mecanismo pero distintos solo en consulta y modificación? 


Para que vean cuantas veces hicieron cosas una y otra vez por ahi sin terminar de verlo y para terminar de explicar el punto voy a dejar un pequeño catalogo de funciones tipicas de funcional


/* 
   foldr(ight) es una funcion que dada una lista, una funcion y un elemento, retorna la aplicacion de la funcion sobre cada item de la lista y el resultado de la ejecucion anterior como segundo parametro (en el caso de la primera ejecucion del a funcion, el segundo parametro es el elemento recibido por parametro. Recorre la lista de izquierda a derecha
  function suma (a,b) { return a + b }


  foldr([1,2,3,4,5,6,7,8,9], suma, 0) = sumatoria de todos esos numeros (no jodan, no voy a calcularlo)

*/
function foldr (list, funct, aux) {
    for(i in list) {
       aux = funct(list[i], aux);
    }
    return aux;
}


/* Foldl(eft) es igual que foldr, pero recorre la lista de derecha a izquierda */


function foldl (list, fn, aux) {
     return foldr(list.reverse(), fn, aux);
}



/*
  fmap es una funcion que aplica una funcion f sobre cada item de una lista y mapea cada resultado en un array que retorna. 


  Ejemplo de uso: 
  
  fmap(even, [1,2,3,4,5,6]) = [false, true, false, true, false, true]


  function nombre (m) { return m.nombre }


  fmap(nombre, [ {nombre:"jacinto" }, {nombre:"elisa" }, {nombre:"ramona" }] = 
   ["jacinto", "elisa", "ramona"] 


  Matematicamente hablando, fmap transforma un conjunto dado aplicando una funcion de transformación
 **/

function fmap (f, array) {
    var retorno = [];
    for (i in array) {
      retorno.push(f(array[i]));
    }

    return retorno;
}




/*
  Filter es una funcion que filtra items de una lista, segun la funcion parametro 


  ejemplo: 


  filter(even, [1,2,3,4,5,6]) = [2,4,6]
 
*/
function filter (fn, array) {
        var retorno = [];
        for (i in array) {
            if(fn(array[i]) retorno.push(array[i]);
        }
        return retorno;    

}



Tengo varias highorder mas, pero no alcanza lo que explique hasta ahora para poder mostrarlas y que tenga sentido, so, keep tuned. El proximo post viene botines de punta con meta-funciones


> perá perá!! como se lo explico a mamá???

A tu vieja decile

 Una funcion de orden superior es como una señora que limpia, vos le decis que consideras desordenado, y como te gustaria que quede, después te desentendes de como lo hace o en que orden.
 

PD: Foldr es muchisimo mas poderosa de lo que explico aca, pero bue, para mas adelante, tenganla en cuenta :)

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.

domingo, 25 de diciembre de 2011

POO, para que se lo cuentes tu vieja

Bueno, como todos saben la programación orientada a objetos es algo que esta en boca de todos, en mente de una menor cantidad de personas y en comprensión de aun menos.

La razón de esto no es que sea algo muy complicado, sino que hay muchas literaturas controversiales, montones de conceptos cruzados, banda de blogs que la explican cosas a partir de tecnologías, niños que creen en los gurues y pelotudos que se creen gurues.

Lamento ser yo quien se los diga: los gurues son los padres, ninguna idea es definitiva, no hay cookbook para la programación de verdad.

Una vez planteado esto, la mejor forma, a mi manera de ver las cosas, de explicar POO es partiendo de una analogia de lo más básico.

Hacer un programa orientado a objetos se trata ni mas ni menos que de concebir entes con comportamiento y hacer que se relacionen entre ellos concibiendo asi un ente aun mas grande al que se le puede pedir que resuelva los problemas que tenemos que resolver.

Ok, tu vieja por ahi asi no lo entiende, vayamos a una analogía:

Suponete que tenemos que construir un edificio ¿Qué necesitamos? Bueno, basandonos en un sistema de trabajo clásico, uno necesita albaniles con distintos conocimientos: levantar paredes, hacer cimientos, hacer columnas, etc. Tambien necesita especialistas de instalaciones: Plomeros, electricistas, gasistas etc. Además necesita supervisores que sepan controlar y tomar decisiones que no pueda tomar el albanil por que no le corresponde (sea por falta de conocimiento o por estar fuera de su responsabilidad), a eso le podemos agregar un ingeniero y/o arquitecto encargado de las decisiones mas generales. Finalmente agregamos diseñadores de ambiente para la parte estética.

Para mantener acotado el ejemplo no vamos a preocuparnos por los materiales y la lógistica de los mismos, supongamos que estan ahi y son infinitos.

Ahora mismo entonces tenemos un monton de gente (entes) que sabe hacer su tarea (reponsabilidad) y que hay que organizar (relación) para que trabajen juntos para resolver los problemas propios del negocio de la construcción.


Que es lo mas importante del ejemplo:
  1. una responsabilidad a grandes rasgos en POO suele estar definida por uno o mas objetos relacionados (asi como levantar una columna implica varias personas de distintos conocimientos trabajando juntos). 
  2. La relación entre los distintos responsables esta dada por el dialogo entre los mismos (envio de mensajes) Obvio, ¿No?
  3. Cada responsable es un pequeño sistema en si que forma parte de uno mas grande que es el encargado de resolver el problema.
  4. El mismo plomero puede trabajar en esta obra o bien cambiando el cuerito de la canilla de tu casa, así como los mismos objetos se pueden usar en varios problemas donde calcen.
Ahora, que es lo que no es extrapolable de este ejemplo:

  1. He escuchado muchas veces 'orientación a objetos es programar la realidad', ok, por suerte eso es mentira, si fuese verdad nunca se hubiese terminado de hacer el primer programa. Solo se programa lo que se necesita. En este caso las relaciones informales - sociales no nos importan.
  2. He escuchado tambien muchas veces que la definición de los objetos esta dada por la realidad. Pero bue, al final uno tiene que mandar un mail basandose en un protocolo que no tiene nada que ver con la realidad, o tiene que hacer un editor de texto y de pronto no existe algo así en la realidad. Al final lo mas razonable es evitar el exceso de realidad y tratar de armar una realidad adhoc.
  3. No existe necesariamente una "cadena de mando" (Suena re milico) en la programación.