Next revision | Previous revision |
teaching:cc4101:tareas:2023-1:tarea2:parte3 [2023/05/11 15:24] – created tvallejos | teaching:cc4101:tareas:2023-1:tarea2:parte3 [2023/05/11 16:50] (current) – [Parte 3. Estrategias de evaluación (2 ptos.)] tvallejos |
---|
La extensión de SL consiste en agregar //modificadores// a los tipos declarados por las funciones funciones, los que especifican el tipo de estrategia a utilizar para los argumentos. A continuación les proveemos una ilustración de este mecanismo y qué es lo que debieran obtener al finalizar esta sección. | La extensión de SL consiste en agregar //modificadores// a los tipos declarados por las funciones funciones, los que especifican el tipo de estrategia a utilizar para los argumentos. A continuación les proveemos una ilustración de este mecanismo y qué es lo que debieran obtener al finalizar esta sección. |
<code scheme> | <code scheme> |
;; La función se declara de tipo (Num -> Num). Sin modificadores significa evaluación temprana. | ;; Una función de tipo Num -> Num significa que se aplicará con evaluación temprana. |
> (run-p-sl '{with {f {fun {Num -> Num} {x} {+ x x}}} | > (run-p-sl '{with {f {fun {x : Num} -> Num : {+ x x}}} |
{f {printn 10}}}) | {f {printn 10}}}) |
(result 20 '("10")) ;; Se imprime una vez, al evaluar el argumento en la aplicación | (result 20 '("10")) ;; Se imprime una vez, al evaluar el argumento en la aplicación |
| |
;; La función se declara (lazy Num -> Num), es decir, se declara el argumento como lazy/call-by-need. | ;; Una función de tipo (lazy Num -> Num), usará evaluación lazy/call-by-need para su argumento. |
> (run-p-sl '{with {f {fun {{lazy Num} -> Num} {x} {+ x x}}} | > (run-p-sl '{with {f {fun {x : {lazy Num}} -> Num : {+ x x}}} |
{f {printn 10}}}) | {f {printn 10}}}) |
(result 20 '("10")) ;; Se imprime una vez cuando se usa el argumento dentro del cuerpo | (result 20 '("10")) ;; Se imprime una vez cuando se usa el argumento dentro del cuerpo |
| |
;; La función se declara (name Num -> Num), es decir, se declara el argumento como name/call-by-name. | ;; Una función de tipo (name Num -> Num), usará evaluación name/call-by-name para su argumento. |
> (run-p-sl '{with {f {fun {{name Num} -> Num} {x} {+ x x}}} | > (run-p-sl '{with {f {fun {x : {name Num}} -> Num : {+ x x}}} |
{f {printn 10}}}) | {f {printn 10}}}) |
(result 20 '("10" "10")) ;; Se imprime dos veces, una por cada uso que se hace del argumento, dentro del cuerpo | (result 20 '("10" "10")) ;; Se imprime dos veces, una por cada uso que se hace del argumento, dentro del cuerpo |
| |
;; Otro ejemplo de lazy. Note que efectivamente al evaluarla se comporta correctamente. | ;; Otro ejemplo de lazy. Note que efectivamente al evaluarla se comporta correctamente. |
> (run-p-sl '{with {f {fun {{lazy Num} -> Num} {x} 1}} | > (run-p-sl '{with {f {fun {x : {lazy Num} -> Num : 1}}} |
{f {printn 10}}}) | {f {printn 10}}}) |
(result 1 '()) ;; No se imprime porque el argumento nunca se usa dentro del cuerpo | (result 1 '()) ;; No se imprime porque el argumento nunca se usa dentro del cuerpo |
| <id> | | <id> |
| {<SL> <SL>} | | {<SL> <SL>} |
| {fun {<sym> : <mtype>} : <mtype> <SL>} ;; note el uso de mtype (tipos con modificadores) | | {fun {<sym> : <mtype>} → <mtype> : <SL>} ;; note el uso de mtype (tipos con modificadores) |
| {printn <SL>} | | {printn <SL>} |
| |
**Hint**: si bien en la sintaxis solo existen dos modificadores, internamente es más conveniente tener 3 (incluyendo uno para eager), así todo tipo tiene un modificador. | **Hint**: si bien en la sintaxis solo existen dos modificadores, internamente es más conveniente tener 3 (incluyendo uno para eager), así todo tipo tiene un modificador. |
| |
**Observaciones**: | <note tip> |
* Note la definición mutuamente recursiva entre ''<type>'' y ''<mtype>''. Esta definición nos permite crear (entre otros tipos) funciones de tipo ''(lazy Num) -> (name Num)'', es decir, una función que toma como argumento una expresión que produce un Num (sin evaluarla, y la evalua de manera lazy si es necesario), y retorna una expresión que produce un Num (sin evaluarla, y deberá ser evaluada tantas veces como sea utilizada). | |
* Se puede pensar ''lazy X'' y ''name X'' como el tipo de las promesas que producen ''X''. | * Se puede pensar ''lazy X'' y ''name X'' como el tipo de las promesas que producen ''X''. |
* Note también que los modificadores solo se pueden aplicar al dominio y al codominio. Por lo que una funcion no puede tener tipo ''{lazy {Num -> Num}}'', pero si tipo ''%%{{lazy {Num -> Num}} -> Num}%%'' o ''{Num -> {lazy {Num -> Num}}}''. | * Note la definición mutuamente recursiva entre ''<type>'' y ''<mtype>''. Esta definición nos permite crear (entre otros tipos) funciones de tipo ''(lazy Num) -> (name Num)'', es decir, una función que toma como argumento una expresión que produce un Num (sin evaluarla, y la evalua de manera lazy si es necesario), y retorna una expresión que produce un Num (sin evaluarla, y deberá ser evaluada tantas veces como sea utilizada). |
| </note> |
---- | ---- |
| |
* Una forma de retrasar la evaluación de una expresión ''%%e%%'', es ponerla en el cuerpo de una lambda ''%%(lambda (_) e)%%''. Luego para evaluarla basta aplicar la función. | * Una forma de retrasar la evaluación de una expresión ''%%e%%'', es ponerla en el cuerpo de una lambda ''%%(lambda (_) e)%%''. Luego para evaluarla basta aplicar la función. |
* Si se requiere una evaluación temprana y el argumento fue declarado lazy o by-name, entonces es necesario ajustarlo para que efectivamente se evalúe en ese punto. | * Si se requiere una evaluación temprana y el argumento fue declarado lazy o by-name, entonces es necesario ajustarlo para que efectivamente se evalúe en ese punto. |
* Si tanto la función como el argumento calzan en la estrategia, entonces no es necesario hacer cambios. | * Si tanto la función como el argumento calzan en la estrategia, entonces no hay nada que hacer. |
* Recuerde que la diferencia entre lazy y by-name es que la primera evalúa una sola vez la expresión y luego "recuerda" el valor para próximos usos. Acuérdese de lo realizado en la Parte 1 con funciones memoizadas! | * Recuerde que la diferencia entre lazy (a.k.a. by-need) y by-name es que la primera evalúa una sola vez la expresión y luego "recuerda" el valor para próximos usos. Acuérdese de lo realizado en la Parte 2 con funciones memoizadas! |
| |
</note> | </note> |
| |
| |