2010-11-03 2 views
6

Я думал, что опубликую это, поскольку я получил его для работы через догадки без реального понимания того, что происходит, и я подумал, что это может быть полезно, если кто-нибудь объяснит это.Разрушающие формы и Compojure?

Я понимаю, как получить на элементе из: Params карты в обработчике Compojure:

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

или

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

хотя я не совсем понимаю, что {some_arg "some_arg"} часть делает :(

Я также хотел получить доступ к части запроса :remote-addr, а также some_arg. И я закончил с

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

Таким образом, я получаю, что котирующиеся строки some_arg и ip имен переменных, к которым я хочу значение связанно, но выше карта не действительна карта Clojure. Как это работает?

Я также получаю, что это оценивается по карте запроса кольца (которая каким-то образом предоставляется макросом defroutes), но выражение выше не является определением функции или макроса, так как оно может существовать как действительное выражение в мой код? Есть ли какая-то приостановка нормальных правил для макросов? Мне не удалось найти определение синтаксиса форм деструктурирования, понятных для этого не-Lisp'er.

+1

Я пропустил факт, что GET - это макрос. Объясняется в ответе ниже ... – edoloughlin

ответ

3

Карта является действующей картой деструктурирования. В любом месте, где вы связываете имена, вы можете использовать деструктурирование. Вы могли бы сделать то же самое в let, как это:

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"] 

Я написал сообщение о карте деструктуризации в контексте названных аргументов, но это применимо и здесь. Вы могли бы найти это полезным: Clojure - named arguments

Есть много постов в блоге демонстрации деструктурирующий, в том числе this один. Я не уверен, какой из них будет каноническим местом для изучения.

Я не притворяюсь, что знаю, что именно делает композиция с этой картой под капотом, но я полагаю, что она бросает ее в путаницу или что-то подобное, как я продемонстрировал выше. GET - это макрос, поэтому ему не нужно оценивать карту, которую вы передаете, поэтому вы не получите ошибку, если она не оценит ее.

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) 

Под капотом магия происходит на эту карту, и она будет передана в функции под названием деструктуризацию, которая делает деструктурирующие магию.

Здесь нет ничего особенного, кроме обычного макроса/специальной формы foo и отложенной оценки.

1

Разрушение происходит в обязательной форме, и для карты деструктурирующие УАК быть связанными находится на левой стороне, а ключ находится справа:

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

Compojure делает обязательную форму за кулисами , так что форма карты деструктурирующих вы использовали выше, эффективно превратилась в нечто вроде:

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

Где request это неявно при условии карты.

В качестве альтернативы, которая просто связывается с картой :params, содержащейся в запросе, является векторная версия (например, [some_arg]).