2011-01-26 14 views
6

Mientras preparaba una respuesta al another question, creé una para mí. Considere el siguiente programa corto.¿Es esto un cierre? Si es así, ¿por qué?

(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)) 

En el detector de acciones, 'timer-action', se modifica el valor del argumento 'contador'. La variable real se declara en la función 'timer-fn', pero se altera en el oyente. En mi experiencia anterior con idiomas como Pascal, hubiera considerado que el 'contador' se pasa por referencia. ¿Es ese el caso aquí o es este un ejemplo de cierre? ¿Algo más?

Gracias por la ayuda.

Respuesta

3

Sí, es un cierre. El contexto léxico de la definición de la función del manejador se conserva, y cuando se invoca posteriormente puede acceder y actualizar las variables que "viven" allí.

No estoy seguro de cómo responder a la pregunta "¿por qué?" aparte de señalar que es simplemente la forma en que se define el lenguaje para que funcione.

+0

Gracias Pointy. Usted * me * dijo por qué - manteniendo el contexto léxico del controlador. Algo que aún me cuesta entender. – clartaq

+0

Pensé que también era difícil, pero solo piense en eso. (...) entonces ... el contexto léxico dice que tienes algo así como (i = 5 ....) entonces yo tengo 5 en cada lugar dentro de los parens. si define una función y esa función usa algo que está fuera de (fn ....) tiene un cierre porque se ve fuera de() de la función para averiguar qué significan las variables. – nickik

Cuestiones relacionadas