2011-01-26 2 views
6

another question에 대한 답변을 준비하면서 직접 만들었습니다. 다음의 짧은 프로그램을 생각해보십시오.폐쇄인가요? 그렇다면 왜?

(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'함수에서 선언되지만 리스너에서 변경됩니다. 파스칼 같은 언어에 대한 나의 초기 경험에서, 나는 '카운터'가 참조로 전달 될 것이라고 생각했을 것이다. 이 사건이 여기에 해당합니까 아니면 이것이 종결의 한 예입니까? 다른 것?

도움 주셔서 감사합니다.

답변

3

예, 폐쇄입니다. 핸들러 함수 정의의 어휘 문맥은 보존되며 나중에 호출 될 때 거기에 "살아"있는 변수에 액세스하고 업데이트 할 수 있습니다.

나는 "왜?"라는 질문에 대답하는 방법을 모르겠습니다. 단순히 언어가 작동하도록 정의 된 방식이라는 것을 지적하는 것 외에는 없습니다.

+0

감사합니다. 왜 핸들러의 어휘 적 맥락을 유지했는지 말해 주었다. 뭔가 머리가 감싸는 데 어려움이 있습니다. – clartaq

+0

나는 그것이 어렵다고 생각했지만 그렇게 생각한다. (...) then ... 어휘 문맥이 당신이 (i = 5 ....와 비슷한 것을 가지고 있다고 말하면, 나는 괄호 안에있는 모든 곳에서 5입니다. 당신이 함수를 정의하고 그 함수가 (fn ....)의 바깥쪽에있는 어떤 것을 사용한다면 함수의 바깥 쪽을보고 변수가 무엇을 의미하는지 알아 내기 때문에 클로저가 있습니다. – nickik

관련 문제