Closures são um padrão de programação no Clojure que permite usar variáveis de um escopo léxico externo dentro de uma função. O Clojure dá suporte a closures de forma transparente, e eles costumam ser usados sem que se saiba o que são.
;; 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 um atom permite preservar um pouco 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 chamada sucessiva a increment incrementa o contador:
(increment)
;;=> 1
(increment)
;;=> 2
Sua empresa de design vinha trabalhando principalmente com transformações CSS para construir páginas web. Depois de algumas conversas, vocês decidem começar a usar Clojure para fazer alguns cálculos dinamicamente. Alguns dos seus colegas de equipe têm menos experiência com Clojure, então você decide usar um closure de função para criar transformações reutilizáveis para pares de coordenadas {x, y}.
Implemente a função translate2d, que retorna uma função usando um closure para realizar uma translação 2D repetível de um par de coordenadas.
(def move-coordinates-right-2px (translate2d 2 0))
(def result (move-coordinates-right-2px 4 8))
;; result => [6 8]
Implemente a função scale2d, que retorna uma função usando um closure para realizar uma escala 2D repetível de um par de coordenadas.
Para este exercício, considere apenas valores de escala positivos.
(def double-scale (scale2d 2 2))
(def result (double-scale 6 -3))
;; result => [12 -6]
Combine duas funções de transformação para realizar uma transformação repetível. Isso costuma ser chamado de composição de funções, em que o resultado da primeira função, 'f(x)', é usado como valor de entrada da segunda função, '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]
Implemente a função memoize-transform. Ela recebe uma função para memorizar e então retorna uma nova função que lembra as entradas da função fornecida, para que o último valor de retorno possa ser "lembrado" e calculado só uma vez caso ela seja chamada novamente com os mesmos argumentos.
A memorização às vezes é chamada de programação dinâmica. Ela permite que operações caras sejam feitas só uma vez, já que o resultado fica guardado.
(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
Crie sua conta no Exercism para aprender e dominar Clojure com 12 conceitos105 exercícios e mentoria humana de verdade, tudo de graça.