En el Cálculo Lambda el paso de parámetros por nombre es equivalente a realizar una reducción en orden normal. Ya que los parámetros reales son reducidos hasta que son utilizado en el cuerpo de la abstracción.
Por ejemplo, la expresión lambda
( (λx. (+ x x)) (+ 1 1) )
la cual es reducida a
( + (+ 1 1) (+ 1 1)) =(+ 2 2)
= 4
es equivalente a realizar un paso de parámetros por nombre.
Observe que el parámetro real es evaluado dos veces. Para evitar esto, podemos crear una estrategia para evitar evaluar más de una vez una expresión. Esta estrategia depende de la implementación que se esté realizando.
Por ejemplo, se pueden usar apuntadores hacia una envoltura que contenga la expresión del parámetro real y una bandera que indique si su contenido ya fue evaluado o no. Si esta envoltura tiene una bandera que indica que no ha sido evaluada se realiza la evaluación de la expresión, se actualiza el valor de la envoltura y se regresa. De otra manera, solamente se regresa el valor de la expresión.
Es importante notar, que la envoltura representa el valor de la expresión, aunque ésta no este evaluada. Esto es así, para que parezca que hemos evaluado los parámetros reales antes que el cuerpo de la función.
Ahora, existen funciones especiales, conocidas como constructores, (como cons de Racket) que también deben seguir el paso de parámetros por nombre, provocando que podamos crear estructuras cíclicas y listas infinitas.
Por ejemplo, si Racket fuera un lenguaje de programación con paso de parámetros por nombre en constructores, podríamos definir la siguiente lista infinita
(define ones (cons 1 ones))
Ya que el segundo parámetro de cons no sera evaluado hasta que se utilice el resto de la lista que construye cons, es decir, cuando se realice la operación cdr (el resto de la lista) sobre ones. Esto es,
(cdr (ones))
Nos devolverá
(cons 1 ones)
Cuando un lenguaje usa paso de parámetros por nombre en funciones y funciones constructoras, pero, además, sólo se realizan una sola vez la evaluación de cada parámetro real, se dice que tiene un régimen de Evaluación Perezosa o paso de parámetros por necesidad (call-by-need), ya que se realiza la evaluación únicamente si es necesaria.
Entre las ventajas que tiene la Evaluación Perezosa, es la posibilidad de trabajar, como ya se menciono, con estructuras cíclicas y listas infinitas. También permite, una implementación más sencilla de corrutinas, ya que permite suspender la ejecución de una función para después reanudarla en el estado donde se quedo.
Por ejemplo, la función
(define (suma-first-n
(lambda (ls n)
(if (= n 0)
0
(+ (car ls)
(suma-first-n (cdr ls)
(- n 1)))))))
Recibe una lista, la cual puede ser infinita, y un entero, regresando la suma de los primeros n elementos de la lista.
Si la función recibe la lista ones definida previamente, ones suspendera su ejecución, regresando un resultado parcial, hasta que se necesiten más datos. Justo lo que hace una corrutina.
Si la función recibe la lista ones definida previamente, ones suspendera su ejecución, regresando un resultado parcial, hasta que se necesiten más datos. Justo lo que hace una corrutina.
No hay comentarios:
Publicar un comentario