Clojure закрытие

на днях я пытался придумать пример закрытия в Clojure. Я придумал и пример, который я видел раньше, и подумал, что это уместно.

Увы, мне сказали, что это нехорошо, и что я должен предоставить что-то с let.

Может ли кто-нибудь пролить свет?

(defn pow [x n] (apply * (repeat x n)))
(defn sq [y] (pow y 2))
(defn qb [y] (pow y 3))

Ответы

Ответ 1

Закрытие - это функция, которая имеет доступ к некоторому именованному значению/переменной вне своей собственной области видимости, поэтому из более высокой области, окружающей эту функцию, когда она была создана (это исключает аргументы функции и локальные именованные значения, созданные внутри этой функции). Ваши примеры не подходят, потому что каждая функция просто использует именованные значения из своих собственных областей.

Пример:

(def foo 
  (let [counter (atom 0)]
    (fn [] (do (swap! counter inc) @counter))))

(foo) ;;=> 1
(foo) ;;=> 2
(foo) ;;=> 3, etc

Теперь foo - это функция, которая возвращает значение атома, выходящего за пределы его объема. Поскольку функция все еще содержит ссылку на этот атом, атом не будет собираться с мусором, если требуется foo.

Ответ 2

Функция, возвращающая функцию i.e функции более высокого порядка являются прекрасными примерами закрытия.

(defn pow [n]
   (fn [x] (apply * (repeat n x))))

(def sq (pow 2))
(def qb (pow 3))

Ответ 3

Другой пример закрытия. Существуют две функции, которые используют одну и ту же среду (state).

(defn create-object [init-state]
  (let [state (atom init-state)]
    {:getter (fn []
               @state)
     :setter (fn [new-val]
               (reset! state new-val))}))

(defn test-it []
  (let [{:keys [setter getter]} (create-object :init-value)]
    (println (getter))
    (setter :new-value)
    (println (getter))))

(test-it)
=> :init-value
   :new-value

Ответ 4

Я хотел иметь что-то, что устанавливает постоянное значение (значения), которое должно использоваться каждый раз.

(def myran 
  (let [constrand (rand)]
    (fn [n] (* n constrand))))


(myran 3)
2.7124521745892096
(myran 1)
0.9041507248630699
(myran 3)
2.7124521745892096

Это значение будет устанавливаться только для значения "constrand". Это очень надуманный пример, но я хотел бы сделать что-то вроде:

JavaScript: The Good Parts

Это от: JavaScript: хорошие части