2010-11-03 6 views
6

Pensé que publicaría esto porque lo hice para resolver conjeturas sin una comprensión real de lo que está pasando y pensé que sería útil si alguien lo explicara.Destructuring forms and Compojure?

entiendo cómo llegar a un elemento de la: params mapa en un manejador Compojure:

(GET "/something" [some_arg] "this is the response body") 

o

(GET "/something" {{some_arg "some_arg"} :params} "this is the response body") 

aunque no entiendo por completo lo que la parte {some_arg "some_arg"} está haciendo :(

También quería acceder a la parte :remote-addr de la solicitud, así como some_arg. Y terminé con

(GET "/something" {{some_arg "some_arg"} :params ip :remote-addr} 
    (do-something-with some_arg ip)) 

Por lo tanto, entiendo que las cuerdas no cotizados some_arg y ip son los nombres de las variables a las que quieren los valores ligados pero el mapa de arriba no es un mapa Clojure válida. ¿Como funciona?

También entiendo que esto se evalúa con el mapa de solicitud de timbre (que de alguna manera es proporcionado por la macro defroutes) pero la expresión anterior no es una función o definición de macro entonces ¿cómo puede 'existir' como una expresión válida en ¿mi código? ¿Hay algún tipo de suspensión de las reglas normales para los macro argumentos? No he podido encontrar una definición de la sintaxis de las formas de desestructuración comprensible para este no Lisp'er.

+1

Eché de menos el hecho de que GET es una macro. Explicado en la respuesta a continuación ... – edoloughlin

Respuesta

3

El mapa es un mapa de desestructuración válido. En cualquier lugar donde enlace nombres, puede usar la desestructuración. Se podría hacer lo mismo en un let, así:

user=> (let [{{some-arg "some_arg"} :params ip :remote-addr} {:remote-addr "127.0.0.1" :params {"some_arg" "some_value"}}] [ip some-arg]) 
["127.0.0.1" "some_value"] 

escribí un post sobre un mapa desestructuración en el contexto de argumentos con nombre, pero se aplica aquí. Es posible que encuentre útil: Clojure - named arguments

Hay una gran cantidad de Publicaciones demostrando desestructuración, incluyendo this uno. No estoy seguro de cuál sería un lugar canónico para aprender.

No pretendo saber qué hace exactamente compojure con ese mapa debajo del capó, pero supongo que lo arroja en un let o algo similar como lo demostré anteriormente. GET es una macro, por lo que no tiene que evaluar el mapa que lo pasa, por lo que no obtendrá un error a menos que lo evalúe.

user=> (defmacro blah [m]) 
#'user/blah 
user=> (blah {a "b" c "d"}) 
nil 
user=> (defn blah [m]) 
#'user/blah 
user=> (blah {a "b" c "d"}) 
java.lang.Exception: Unable to resolve symbol: a in this context (NO_SOURCE_FILE:9) 

Debajo del capó, la magia le sucede a ese mapa y se pasa a una función llamada desestructuración que hace la magia desestructuradora.

No hay nada especial pasando aquí aparte de la macro/forma especial foo y evaluación diferida.

1

Destructing tiene lugar dentro de una forma de unión, y para el mapa desestructurar el var en obligarse está a la izquierda, y la clave está en la derecha:

 
user=> (let [{a :foo} {:foo :bar}] 
user=* a) 
:bar 

Compojure está haciendo una forma de unión entre bastidores , de manera que forman un mapa desestructuración que estaba utilizando anteriormente se convirtió efectivamente en algo así como:

 
(let [{{some_arg "some_arg"} :params} request] 
    ...) 

Dónde request es un mapa que aparece de forma implícita.

La versión de vector (por ejemplo, [some_arg]) es una alternativa que solo se une al mapa :params que figura en la solicitud.

Cuestiones relacionadas