座標轉換

座標轉換

學習練習

簡介

閉包是 Clojure 裡的一種程式設計模式,它允許外部詞法作用域的變數在函式內部使用。Clojure 對閉包的支援是透明的,而且常常在不知道它們是什麼的情況下就用到它們。

;; 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 比較不熟悉,所以你決定用函式閉包,為{x, y}座標對建立可重複使用的轉換。

1. 平移座標

實作 translate2d 函式,它會回傳一個使用閉包的函式,用來對座標對進行可重複的 2D 平移。

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

2. 縮放座標

實作 scale2d 函式,它會回傳一個使用閉包的函式,用來對座標對進行可重複的 2D 縮放。

在這道練習中,假設縮放值都是正數。

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

3. 組合轉換函式

組合兩個轉換函式來執行可重複的轉換。這通常稱為_函式組合_,也就是把第一個函式 '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]

4. 儲存函式的結果

實作 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
透過 GitHub 編輯 連結會在新視窗或分頁中開啟
Clojure Exercism

準備好開始 座標轉換 了嗎?

註冊 Exercism,透過 12 個概念105 個練習 和真人引導來學習並精通 Clojure,全部免費。