2011-03-28 18 views
6

En el compojure library in the core namespace, veo la siguiente forma:clojure: ¿Cuál es el uso de la forma # '/ (var ...)?

(defn- compile-route 
    "Compile a route in the form (method path & body) into a function." 
    [method route bindings body] 
    `(#'if-method ~method 
    (#'if-route ~(prepare-route route) 
     (fn [request#] 
     (let-request [~bindings request#] 
      (render (do [email protected]) request#)))))) 

y

(defmacro GET "Generate a GET route." 
    [path args & body] 
    (compile-route :get path args body)) 

Más arriba en el archivo, los if-method y if-route funciones se definen con defn- s.

No entiendo el significado del #' en esta función compile-route. Los documentos para (var ...) dicen:

El símbolo debe resolverse en una var, y se devuelve el objeto Var en sí (no su valor). El lector macro # 'x se expande a (var x).

Pero para mí, en el contexto de lo que está sucediendo (es decir, ser llamado desde un defmacro), suena como si significara se devolverá el valor del símbolo, lo que es lo mismo que lo que suena de sustitución como :

(def x 5) 
(+ x 7) 
-> 12 

es decir, (+ x 7) expande a, o es la misma que, (+ 5 7)

Qué me estoy perdiendo aquí?

Respuesta

4

Después de mirar esto por un rato, estoy empezando a sospechar que tiene algo que ver con el hecho de que los if-method y funciones son if-route en realidad privado ((defn- if-route ...)).

Además, para las macros, cuando se hace la cita de back-tick ("`") en realidad se está consiguiendo el símbolo totalmente espacio de nombres especificado en la expansión final:

`(+ 2 3) 

se expandiría a

(clojure.core/+ 2 3) 

Dado que estos métodos son privados, no se podrá acceder a ellos en la expansión normal, por lo tanto se usa la función var para obtener el símbolo que contiene una referencia a la función real que debe invocarse en este momento la expansión.

+1

Este es exactamente el motivo. – kotarak

+0

¡Gracias por la confirmación! –

+0

Un comentario más: los símbolos no contienen referencias. Vars do. Esta es una diferencia para Lisp, IIUC. Los símbolos son solo nombres y el compilador los resuelve en Vars. El código funciona, porque Var delega todas las llamadas '.invoke' a lo que contiene. – kotarak

3

ring-reload puede volver a cargar las definiciones var de los archivos que sigue modificando durante el desarrollo. Como transfiere un (var ...), se resuelve cada vez que intenta leerlo, y como consecuencia los vars recargados se pueden volver a leer en cada solicitud. Esto conduce al desarrollo web interactivo (sin necesidad de compilar, etc.). Si no usa (var ...) y pasa el valor directamente, los vars recargados no se pasarán a los controladores URI de anillo y, por lo tanto, no puede simplemente modifica y ejecuta tu código.

Marque esta entrada del blog, por ejemplo:

http://charsequence.blogspot.com/2010/09/interactive-web-development-with.html

Cuestiones relacionadas