2011-01-26 8 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

関連する問題