As closures são um padrão de programação em Clojure que permite usar variáveis de um âmbito lexical exterior dentro de uma função. O Clojure suporta closures de forma transparente, e muitas vezes usam-se sem se saber 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 algum 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 seu contador:
(increment)
;;=> 1
(increment)
;;=> 2
A tua empresa de design tem trabalhado sobretudo com transformações de CSS para construir páginas web. Depois de alguma discussão, decidiu-se começar a usar Clojure para fazer alguns cálculos de forma dinâmica. Alguns dos teus colegas de equipa têm menos experiência com Clojure, por isso decides usar um closure para criar transformações reutilizáveis para pares de coordenadas {x, y}.
Implementa a função translate2d que devolve uma função que usa um closure para fazer 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]
Implementa a função scale2d que devolve uma função que usa um closure para fazer uma escala 2d repetível de um par de coordenadas.
Neste exercício, assume apenas valores de escala positivos.
(def double-scale (scale2d 2 2))
(def result (double-scale 6 -3))
;; result => [12 -6]
Combina duas funções de transformação para fazer uma transformação repetível. A isto chama-se muitas vezes 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]
Implementa a função memoize-transform. Recebe uma função para memorizar e devolve uma nova função que se lembra dos parâmetros de entrada da função fornecida, para que o último valor devolvido possa ser "memorizado" e só seja calculado uma vez, caso a função seja chamada de novo com os mesmos argumentos.
A memorização é por vezes chamada de programação dinâmica: permite que operações dispendiosas sejam feitas apenas uma vez, uma vez que o seu resultado fica memorizado.
(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
Inscreve-te no Exercism para aprenderes e dominares Clojure com 12 conceitos105 exercícios, e mentoria humana real, tudo grátis.