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

相关问题