Posted by & filed under computación, programacion.

pygmy-sloth-mangroves_71212

Seguramente hayas leído por ahí alguna vez “Work smarter, not harder” y estas últimas semanas cursando en la facultad Teoría de Lenguaje cuyo libro guía es “Concepts, Techniques and models of computer programming” me topé con un concepto de programación que lleva el lema a no sólo ahorrar recursos mentales sino también computacionales.

Supongamos que necesitamos una estructura de datos, digamos una lista, que contenga TODOS los números naturales pares (incluyendo el 0) para que sean accesibles a consulta con un L[pos] = numero par nº pos. Con esta situación se nos vienen dos cosas a la mente, NUNCA vamos a lograr completar la lista ni tampoco vamos a poder consultarla entera. Pero entendemos que en la práctica vamos a hacer consultas acotadas a cierto rango (no infinito) pero potencialmente muy grande. Computacionalmente completar una lista cuasi infinita es muy demandante de recursos.

Entonces, ¿como completamos una lista sin devorarnos recursos? No la completamos 🙂
La idea de la Evaluación Perezosa es que el cálculo se haga única y exclusivamente cuando se solicita el dato requerido. Veamos un poco de código (el lenguaje es Oz):

declare Ints
fun lazy {Ints N}
 N|{Ints N+2}
end
L={Ints 0}

Para poder entender un poco el código, hace falta explicar como Oz maneja las listas y hay varias maneras de verlo. Podemos ver la lista como un Head | Tail, donde el Head es el primer elemento de la lista y el Tail todo lo demás. Por ejemplo la lista [1 2 3 4] Head=1 Tail=[2 3 4] (como vemos el Tail es una lista, por lo que a su vez también tiene un Head y Tail).

Otra manera de verlo es como un arbol:

625503_10151506001475782_1047826088_n

Si hacemos un Browse (muestra en pantalla) L.1 accederemos al Head y nos devolverá 0.
Ahora vayamos un pasito más adelante y accedamos al Tail. Normalmente si hacemos L.2 nos devolvería la lista que contiene todos los demás elementos de la lista, pero como la función la declaramos perezosa todavía no se ejecutó el llamado recursivo {Ints N+2}. Ahora si efectuamos L.2.1 (accedemos al head del tail) ahí sí se efectuará el llamado a la función y nos devolverá 2. Y el resto es análogo.

El detalle radica en cuando se hace ese llamado recursivo, si en el momento que se inicializa la lista, o en el momento que se intenta obtener el valor.
Para ver la diferencia se puede intentar hacer un {Browse L.2} con y sin lazy, no sin antes establecer condiciones a N (N

604095_10151506025035782_125189951_n

485189_10151506025020782_2063841031_n

Como vemos en un caso podemos mostrar el Tail mientras que en otro no.

Mmm, no se si entendí

No te preocupes, yo tuve que escribir algo de código, probar variaciones etc para entenderlo un poco más. Imaginate que tenes muchos hermanos y tu vieja te pide que pongas la mesa (si sos el más chico de una familia numerosa sabés de lo que hablo), PERO no sabés cuantos de tus hermanos van a ir a comer. Podés elegir poner la mesa considerando que van a ir todos tus hermanos, o ir poniendo los platos concorde vayan presentandose a comer. Creo que ahí pudo haber quedado más claro, se trata de ser “vago” pero de manera inteligente, guardando el esfuerzo para cuando realmente sea necesario.

Esta es una herramienta para dado el caso “mover” la instancia de cómputo de una instancia a otra, sea por cuestiones de eficiencia, consumo de recursos, lo que fuere.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *