Los closures son un patrón de programación en Clojure que permite usar variables de un ámbito léxico externo dentro de una función. Clojure admite los closures de forma transparente, y muchas veces se usan sin saber qué son.
;; Top-level definitions are global-scope
(def dozen 12)
;; Functions create a new scope.
;; Referencing the outer variable here is a closure.
(fn [n] (* dozen n))
Usar un atom permite conservar algo de estado:
;; This function closure increments the counter's state
;; in the outer lexical context.
;; This way the counter can be shared between many calling contexts.
(def increment
(let [counter (atom 0)]
(fn [] (swap! counter inc))))
Cada llamada sucesiva a increment incrementa su contador:
(increment)
;;=> 1
(increment)
;;=> 2
Tu empresa de diseño ha trabajado principalmente con transformaciones CSS para crear páginas web. Después de algunas conversaciones, se decidió empezar a usar Clojure para hacer algunos cálculos de forma dinámica. Algunos de tus compañeros tienen menos experiencia con Clojure, así que decides usar una clausura para crear transformaciones reutilizables para pares de coordenadas {x, y}.
Implementa la función translate2d que devuelve una función que hace uso de una clausura para realizar una traslación 2D repetible de un par de coordenadas.
(def move-coordinates-right-2px (translate2d 2 0))
(def result (move-coordinates-right-2px 4 8))
;; result => [6 8]
Implementa la función scale2d que devuelve una función que hace uso de una clausura para realizar un escalado 2D repetible de un par de coordenadas.
Para este ejercicio, asume solo valores de escalado positivos.
(def double-scale (scale2d 2 2))
(def result (double-scale 6 -3))
;; result => [12 -6]
Combina dos funciones de transformación para realizar una transformación repetible. A esto se le suele llamar composición de funciones, donde el resultado de la primera función 'f(x)' se usa como argumento de la segunda función 'g(x)'.
(def move-coordinates-right-2px (translate2d 2 0))
(def double-coordinates (scale2d 2 2))
(def composed-transformations
(compose-transform move-coordinates-right-2px
double-coordinates))
(def result (composed-transformations 0 1))
;; result => [4 2]
Implementa la función memoize-transform. Recibe una función para memorizar y después devuelve una función nueva que recuerda los argumentos de la función recibida, de modo que el último valor devuelto se pueda «recordar» y solo se calcule una vez si se vuelve a llamar con los mismos argumentos.
A la memorización a veces se le llama programación dinámica; permite que las operaciones costosas se hagan solo una vez, ya que su resultado se recuerda.
(def triple-scale (scale2d 3 3))
(def memoized-scale (memoize-transform triple-scale))
(memoized-scale 4 3)
;; => [12, 9], this is computed since it hasn't been computed before for the arguments
(memoized-scale 4 3)
;; => [12, 9], this is remembered, since it was computed already
Regístrate en Exercism para aprender y dominar Clojure con 12 conceptos105 ejercicios y mentoría humana real, todo gratis.