Both sides previous revisionPrevious revisionNext revision | Previous revision |
teaching:cc4101:tareas:2025-1:tarea2:parte2 [2025/05/11 19:51] – [Parte 2. Memoización (2 ptos.)] msegur | teaching:cc4101:tareas:2025-1:tarea2:parte2 [2025/05/14 16:52] (current) – [Parte 2. Memoización (2 ptos.)] dibanez |
---|
[[teaching:cc4101:tareas:2025-1:tarea2|<< Volver]] | [[teaching:cc4101:tareas:2025-1:tarea2|<< Volver]] |
===== Parte 2. Memoización (2 ptos.) ===== | ===== Parte 2. Memoización (2 ptos.) ===== |
En esta sección van a extender el lenguaje CL con un mecanismo de [[https://es.wikipedia.org/wiki/Memoizaci%C3%B3n|memoización]]. La memoización es una técnica de optimización que permite evaluar más rápidamente llamadas a funciones. Una función memoizada tiene asociada una estructura (p.ej. tabla de hash) donde se van guardando los argumentos con que se aplica la función y el resultado de evaluar la función con esos argumento. Luego, si se realiza una nueva aplicación con el mismo argumento, basta con acceder a la memoria para obtener el valor resultante, sin tener que evaluar todo el cuerpo de la función de nuevo. | En esta sección van a extender el lenguaje CL con un mecanismo de [[https://es.wikipedia.org/wiki/Memoizaci%C3%B3n|memoización]]. La memoización es una técnica de optimización que permite evaluar más rápidamente llamadas a funciones. Una función memoizada tiene asociada una estructura (p.ej. tabla de hash) donde se van guardando los argumentos con que se ha aplicado la función y el resultado de evaluar la función con esos argumentos. Luego, si se realiza una nueva aplicación con el mismo argumento, basta con acceder a la memoria para obtener el valor computado anteriormente, sin tener que evaluar todo el cuerpo de la función de nuevo. |
| |
* (0.3 ptos) Extienda la sintaxis del lenguaje (y por ende, el parser) con la expresión ''{mfun {<id>} <CL>}'' que permite definir una función anónima memoizada. | * (0.4 ptos) Extienda la sintaxis del lenguaje (y por ende, el parser) con la expresión ''{mfun {<id>} <CL>}'' que permite definir una función anónima memoizada. |
* (0.2 ptos) Extienda el tipo de dato de los valores con un nuevo constructor ''mclosV'' para representar una función memoizada en tiempo de ejecución. La única diferencia con clausuras tradicionales es la presencia de una tabla de memoización. | * (0.3 ptos) Extienda el tipo de dato de los valores con un nuevo constructor ''mclosV'' para representar una función memoizada en tiempo de ejecución. La única diferencia con clausuras tradicionales es la presencia de una tabla de memoización. |
| |
<note> Un ejemplo de una aplicación de este concepto es la librería functools de Python, que posee un [[https://docs.python.org/3/library/functools.html#functools.lru_cache|decorador]] para memoizar los llamados de función y así ahorrar tiempo cuando se llama periódicamente a función con los mismos argumentos.</note> | <note> Un ejemplo de una aplicación de este concepto es la librería functools de Python, que posee un [[https://docs.python.org/3/library/functools.html#functools.lru_cache|decorador]] para memoizar los llamados de función y así ahorrar tiempo cuando se llama periódicamente a función con los mismos argumentos.</note> |
</code> | </code> |
| |
* (1 pto) Modifique el intérprete para que soporte funciones memoizadas. Recuerde que cada aplicación de una función memoizada debe obtener el valor registrado en la tabla de memoización, y de no estarlo, registrarlo para usos posteriores. | * (1.3 ptos) Modifique el intérprete para que soporte funciones memoizadas. Recuerde que cada aplicación de una función memoizada debe obtener el valor registrado en la tabla de memoización, y de no estarlo, registrarlo para usos posteriores. |
* (0.5 ptos) Usando lo realizado en la Parte 1, implemente tests que evidencien que una función memoizada efectivamente no vuelve a ejecutar su cuerpo cuando la vuelven a aplicar con el mismo argumento. | |
| |
<note important>Considere la función con memoización ''doble''. Si un programa ejecutara | <note important>Considere la función con memoización ''doble'', que evalúa su argumento dos veces. Si un programa ejecutara |
<code>{doble {printn 3}} | <code>{doble {printn 3}} |
{doble {printn 3}} | {doble {printn 3}} |
| |
**Observaciones**: | **Observaciones**: |
| * Recuerde testear las extensiones realizadas, para ello es utilize lo realizado en la Parte 1, debe verificar que una función memoizada no vuelve a ejecutarse si se llama con los mismos argumentos. |
* Cada ''mfun'' tiene su propia memoria. | * Cada ''mfun'' tiene su propia memoria. |
* Si usan los valores del lenguaje como llaves, se van a encontrar con problemas con el mecanismo de hashing normal dado que los valores son mutables (por las tablas de hash de memoización) ((ver [[https://docs.racket-lang.org/reference/hashtables.html#(elem._(caveat._mutable-keys))|documentación]] sobre hash tables y valores mutables.)). Para resolver este problema, en vez de usar ''make-hash'' para crear sus tablas de hash, tienen que usar ''make-hashalw'': este constructor retorna una tabla que usa ''equal-always?''((ver [[https://docs.racket-lang.org/reference/Equality.html#%28def._%28%28quote._~23~25kernel%29._equal-always~3f%29%29|documentación]] sobre igualdad de estructuras y mutación.)) para comparar llaves y por ende se comporta de manera coherente con llaves mutables. | * Si usan los valores del lenguaje como llaves, se van a encontrar con problemas con el mecanismo de hashing normal dado que los valores son mutables (por las tablas de hash de memoización) ((ver [[https://docs.racket-lang.org/reference/hashtables.html#(elem._(caveat._mutable-keys))|documentación]] sobre hash tables y valores mutables.)). Para resolver este problema, en vez de usar ''make-hash'' para crear sus tablas de hash, tienen que usar ''make-hashalw'': este constructor retorna una tabla que usa ''equal-always?''((ver [[https://docs.racket-lang.org/reference/Equality.html#%28def._%28%28quote._~23~25kernel%29._equal-always~3f%29%29|documentación]] sobre igualdad de estructuras y mutación.)) para comparar llaves y por ende se comporta de manera coherente con llaves mutables. |
| |