A closure egy Clojure-beli programozási minta, amely lehetővé teszi, hogy egy függvényen belül egy külső lexikális scope változóit használd. A Clojure transzparensen támogatja a closure-öket, és gyakran anélkül használjuk őket, hogy tudnánk, mik is azok.
;; 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))
Egy atom segítségével megőrizhetünk bizonyos állapotot:
;; 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))))
Az increment minden további hívása növeli a számlálóját:
(increment)
;;=> 1
(increment)
;;=> 2
A tervezőcég, ahol dolgozol, eddig elsősorban CSS-transzformációkkal épített weboldalakat. Egy kis megbeszélés után úgy döntötök, hogy a dinamikus számításokat mostantól Clojure-rel végzitek. Néhány kollégád kevésbé járatos a Clojure-ben, ezért úgy döntesz, hogy egy függvény-closure segítségével hozol létre újrahasznosítható transzformációkat {x, y} koordinátapárokhoz.
Valósítsd meg a translate2d függvényt. Ez egy olyan függvényt ad vissza, amely egy closure-t használva egy koordinátapár ismételhető kétdimenziós eltolását végzi el.
(def move-coordinates-right-2px (translate2d 2 0))
(def result (move-coordinates-right-2px 4 8))
;; result => [6 8]
Valósítsd meg a scale2d függvényt. Ez egy olyan függvényt ad vissza, amely egy closure-t használva egy koordinátapár ismételhető kétdimenziós skálázását végzi el.
Ehhez a feladathoz feltételezd, hogy csak pozitív skálázási értékek fordulnak elő.
(def double-scale (scale2d 2 2))
(def result (double-scale 6 -3))
;; result => [12 -6]
Fűzz össze két transzformációs függvényt egy ismételhető transzformációhoz. Ezt gyakran függvénykompozíciónak nevezik, ahol az első függvény, 'f(x)' eredménye lesz a második függvény, 'g(x)' bemenete.
(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]
Valósítsd meg a memoize-transform függvényt. Ez egy memoizálandó függvényt vesz át, majd visszaad egy új függvényt, amely megjegyzi a kapott függvény bemeneteit, így a legutóbbi visszatérési érték „megjegyezhető”, és csak egyszer számítódik ki, ha ugyanazokkal az argumentumokkal hívják meg újra.
A memoizálást néha dinamikus programozásnak is nevezik; lehetővé teszi, hogy a költséges műveleteket csak egyszer hajtsuk végre, mivel az eredményüket megjegyzi.
(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
Iratkozz fel az Exercism-re, hogy megtanuld és elsajátítsd a(z) Clojure nyelvet 12 fogalom105 feladat segítségével, valódi emberi mentorálással, mindez ingyen.