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: хорошие части