Τα Closures είναι ένα μοτίβο προγραμματισμού στην Clojure που επιτρέπει να χρησιμοποιούνται μέσα σε μια συνάρτηση μεταβλητές από ένα εξωτερικό λεξικό πεδίο. Η Clojure υποστηρίζει τα closures διαφανώς, και συχνά χρησιμοποιούνται χωρίς να ξέρει κανείς τι είναι.
;; 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))
Η χρήση ενός atom επιτρέπει να διατηρηθεί κάποια κατάσταση:
;; 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))))
Κάθε διαδοχική κλήση της increment αυξάνει τον μετρητή της:
(increment)
;;=> 1
(increment)
;;=> 2
Η εταιρεία σχεδιασμού σου έχει δουλέψει κυρίως με μετασχηματισμούς CSS για να φτιάχνει ιστοσελίδες. Μετά από κάποια συζήτηση, αποφασίζεται να αρχίσει η ομάδα να χρησιμοποιεί Clojure για κάποιους δυναμικούς υπολογισμούς. Κάποιοι από τους συναδέλφους σου έχουν λιγότερη εμπειρία με την Clojure, οπότε αποφασίζεις να χρησιμοποιήσεις ένα closure συνάρτησης για να δημιουργήσεις επαναχρησιμοποιήσιμους μετασχηματισμούς για ζεύγη συντεταγμένων {x, y}.
Υλοποίησε τη συνάρτηση translate2d, η οποία επιστρέφει μια συνάρτηση που χρησιμοποιεί ένα closure για να εκτελεί μια επαναλαμβανόμενη διδιάστατη μετατόπιση ενός ζεύγους συντεταγμένων.
(def move-coordinates-right-2px (translate2d 2 0))
(def result (move-coordinates-right-2px 4 8))
;; result => [6 8]
Υλοποίησε τη συνάρτηση scale2d, η οποία επιστρέφει μια συνάρτηση που χρησιμοποιεί ένα closure για να εκτελεί επαναλαμβανόμενη διδιάστατη κλιμάκωση ενός ζεύγους συντεταγμένων.
Για αυτή την άσκηση, θεώρησε ότι οι τιμές κλιμάκωσης είναι μόνο θετικές.
(def double-scale (scale2d 2 2))
(def result (double-scale 6 -3))
;; result => [12 -6]
Συνδύασε δύο συναρτήσεις μετασχηματισμού για να εκτελέσεις έναν επαναλαμβανόμενο μετασχηματισμό. Αυτό συχνά ονομάζεται σύνθεση συναρτήσεων, όπου το αποτέλεσμα της πρώτης συνάρτησης 'f(x)' χρησιμοποιείται ως είσοδος στη δεύτερη συνάρτηση '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]
Υλοποίησε τη συνάρτηση memoize-transform. Παίρνει μια συνάρτηση προς απομνημόνευση και μετά επιστρέφει μια νέα συνάρτηση που θυμάται τις εισόδους της συνάρτησης που της δίνεται, ώστε η τελευταία τιμή επιστροφής να μπορεί να "θυμάται" και να υπολογίζεται μόνο μία φορά αν κληθεί ξανά με τα ίδια ορίσματα.
Η απομνημόνευση μερικές φορές ονομάζεται δυναμικός προγραμματισμός και επιτρέπει να γίνονται οι δαπανηρές λειτουργίες μόνο μία φορά, αφού το αποτέλεσμά τους θυμάται.
(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
Γράψου στο Exercism για να μάθεις και να κατακτήσεις Clojure με 12 έννοιες105 ασκήσεις και πραγματική καθοδήγηση από ανθρώπους, όλα δωρεάν.