Это закрытие?Если так, то почему? - PullRequest
6 голосов
/ 26 января 2011

Готовя ответ на другой вопрос , я создал его для себя.Рассмотрим следующую короткую программу:

(ns net.dneclark.JFrameAndTimerDemo
  (:import (javax.swing JLabel JButton JPanel JFrame Timer))
  (:gen-class))

(defn timer-action [label counter]
 (proxy [java.awt.event.ActionListener] []
   (actionPerformed
     [e]
      (.setText label (str "Counter: " (swap! counter inc))))))

(defn timer-fn []
  (let [counter (atom 0)
        label (JLabel. "Counter: 0")
        timer (Timer. 1000 (timer-action label counter))
        panel (doto (JPanel.)
                (.add label))]
    (.start timer)
    (doto (JFrame. "Timer App")
      (.setContentPane panel)
      (.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE)
      (.setLocation 300 300)
      (.setSize 200 200)
      (.setVisible true))))

(defn -main []
  (timer-fn))

В слушателе действия 'timer-action' значение аргумента 'counter' изменяется.Фактическая переменная объявляется в функции timer-fn, но изменяется в слушателе.В моем предыдущем опыте работы с такими языками, как Паскаль, я бы посчитал, что «counter» передается по ссылке.Это тот случай, или это пример закрытия?Что-то еще?

Спасибо за помощь.

1 Ответ

3 голосов
/ 26 января 2011

Да, это закрытие. Лексический контекст определения функции-обработчика сохраняется, и при последующем ее вызове он может обращаться и обновлять переменные, которые там «живут».

Я не уверен, как ответить на вопрос "почему?" кроме того, чтобы указать, что это просто способ определения языка для работы.

...