2011-01-26 295 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'函數中聲明,但在偵聽器中更改。在我以前使用Pascal語言的經驗中,我認爲'counter'是通過引用傳遞的。這是這種情況還是這是關閉的例子?還有別的嗎?

感謝您的幫助。

回答

3

是的,這是一個封閉。處理函數定義的詞法上下文被保留下來,並且在稍後調用它時,它可以訪問和更新那裏的「活着」變量。

我不知道如何回答這個問題,「爲什麼?」除了指出這只是語言定義的工作方式。

+0

謝謝Pointy。你*確實*告訴我爲什麼 - 維護處理程序的詞法上下文。我仍然有困難纏着我的頭。 – clartaq

+0

我覺得這很難,但只是想到這一點。 (...)然後......是詞彙語境,表示你有類似的東西(i = 5 ....),那麼我就是每個在parens裏面的地方。如果你定義了一個函數,並且該函數正在使用(fn ....)以外的東西,那麼你有一個閉包,因爲它看起來不在函數的()中,以查明變量的含義。 – nickik

相關問題