Parcours
/
Clojure
Clojure
/
Exercices
/
Transformation de coordonnées
Transformation de coordonnées

Transformation de coordonnées

Exercice d'apprentissage

Introduction

Les closures sont un modèle de programmation en Clojure qui permet d'utiliser des variables issues d'une portée lexicale externe à l'intérieur d'une fonction. Clojure prend en charge les closures de façon transparente, et on les utilise souvent sans savoir ce qu'elles sont.

;; 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))

Closures pour conserver l'état et transmettre des valeurs

Utiliser un atom permet de conserver un peu d'état :

;; 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))))

Chaque appel successif à increment incrémente son compteur :

(increment)
;;=> 1
(increment)
;;=> 2

Instructions

Ton entreprise de design a surtout travaillé avec des transformations CSS pour construire des pages web. Après quelques discussions, il est décidé de commencer à utiliser Clojure pour effectuer certains calculs de façon dynamique. Certains de tes collègues connaissent moins bien Clojure, tu décides donc d'utiliser une fermeture de fonction pour créer des transformations réutilisables pour des paires de coordonnées {x, y}.

1. Translater les coordonnées

Implémente la fonction translate2d, qui renvoie une fonction utilisant une fermeture pour effectuer une translation 2D répétable d'une paire de coordonnées.

(def move-coordinates-right-2px (translate2d 2 0))
(def result (move-coordinates-right-2px 4 8))
;; result => [6 8]

2. Mettre les coordonnées à l'échelle

Implémente la fonction scale2d, qui renvoie une fonction utilisant une fermeture pour mettre une paire de coordonnées à l'échelle de façon répétable.

Pour cet exercice, suppose que les valeurs de mise à l'échelle sont toujours positives.

(def double-scale (scale2d 2 2))
(def result (double-scale 6 -3))
;; result => [12 -6]

3. Composer des fonctions de transformation

Combine deux fonctions de transformation pour effectuer une transformation répétable. On appelle souvent cela la composition de fonctions : le résultat de la première fonction 'f(x)' sert d'entrée à la seconde fonction '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]

4. Enregistrer les résultats des fonctions

Implémente la fonction memoize-transform. Elle prend une fonction à memoize, puis renvoie une nouvelle fonction qui se souvient des entrées de la fonction fournie, de sorte que la dernière valeur de retour puisse être « mémorisée » et ne soit calculée qu'une seule fois si on l'appelle à nouveau avec les mêmes arguments.

La mémorisation est parfois appelée programmation dynamique ; elle permet de n'effectuer qu'une seule fois des opérations coûteuses, puisque leur résultat est mémorisé.

(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
Modifie via GitHub Le lien s'ouvre dans une nouvelle fenêtre ou un nouvel onglet
Clojure Exercism

Prêt à commencer Transformation de coordonnées ?

Inscris-toi sur Exercism pour apprendre et maîtriser Clojure avec 12 concepts105 exercices, et un vrai mentorat humain, le tout gratuitement.