2013-02-14 2 views
15

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

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

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

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

ответ

20

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

Пример:

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

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

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

14

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

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

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

Привет, так что мой пример будет замыкание, если я определил тело моей мощи, как и вы (закрытие было anon f)? – Eddy

+0

Да, это был бы один из способов описания закрытия – Ankur

+0

+1 Элегантный пример! –

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 
+1

спасибо, отличный пример!) – Eddy

-1

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

(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: The Good Parts

Смежные вопросы