Skip to content

Instantly share code, notes, and snippets.

@BadUncleX
Last active April 11, 2018 05:47
Show Gist options
  • Save BadUncleX/3964a1674f6dcb96358f to your computer and use it in GitHub Desktop.
Save BadUncleX/3964a1674f6dcb96358f to your computer and use it in GitHub Desktop.
On closures
;; the snippet from `the joy of clojure 2nd'
;; mutable var could be as global var
(def add-and-get
(let [ai (java.util.concurrent.atomic.AtomicInteger.)]
(fn [y] (.addAndGet ai y))))
(add-and-get 2)
;=> 2
(add-and-get 2)
;=> 4
(add-and-get 7)
;=> 11
;; Functions returning closures
(defn times-n [n]
(let [x n]
(fn [y] (* y x))))
(times-n 4)
(def times-four (times-n 4))
(times-four 10)
;=> 40
;; Closing over parameters
;; skip let
(defn times-n [n]
(fn [y] (* y n)))
(defn divisible [denom]
(fn [num]
(zero? (rem num denom))))
((divisible 3) 6)
;=> true
((divisible 3) 7)
;=> false
;; Passing closures as functions
(filter even? (range 10))
;=> (0 2 4 6 8)
;; Note that filter only ever passes a single argument to the predicate given it. Without
;; closures, this might be restrictive, but with them you can close over the values needed:
(filter (divisible 4) (range 10))
;=> (0 4 8)
(defn filter-divisible [denom s]
(filter #(zero? (rem % denom)) s))
(filter-divisible 5 (range 20))
;=> (0 5 10 15)
;; Sharing closure context
(def bearings [{:x 0, :y 1} ; north
{:x 1, :y 0} ; east
{:x 0, :y -1} ; south
{:x -1, :y 0}]) ; west
(defn forward [x y bearing-num]
[(+ x (:x (bearings bearing-num)))
(+ y (:y (bearings bearing-num)))])
(defn bot [x y bearing-num]
{:coords [x y]
:bearing ([:north :east :south :west] bearing-num)
:forward (fn [] (bot (+ x (:x (bearings bearing-num)))
(+ y (:y (bearings bearing-num)))
bearing-num))
:turn-right (fn [] (bot x y (mod (+ 1 bearing-num) 4)))
:turn-left (fn [] (bot x y (mod (- 1 bearing-num) 4)))})
(:bearing ((:forward ((:forward ((:turn-right (bot 5 5 0))))))))
;=> :east
(:coords ((:forward ((:forward ((:turn-right (bot 5 5 0))))))))
;=> [7 5]
(defn mirror-bot [x y bearing-num]
{:coords [x y]
:bearing ([:north :east :south :west] bearing-num)
:forward (fn [] (mirror-bot (- x (:x (bearings bearing-num)))
(- y (:y (bearings bearing-num)))
bearing-num))
:turn-right (fn [] (mirror-bot x y (mod (- 1 bearing-num) 4)))
:turn-left (fn [] (mirror-bot x y (mod (+ 1 bearing-num) 4)))})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment