2010-11-03 73 views
6

我以爲我會發布這個,因爲我沒有真正理解發生的事情,通過猜測工作,我認爲如果有人解釋它可能會有幫助。解構形式和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"}部分做:在處理的Compojure地圖PARAMS :(

我也想訪問:remote-addr部分請求以及some_arg我最後用

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

所以,我得到的是不帶引號的字符串some_argip是變量的名字,而我想要的值約束,但上面的圖是不是一個有效的Clojure地圖。它是如何工作的?

我還得到這是根據Ring請求映射(它由某種方式由defroutes宏提供)評估的,但上面的表達式不是函數或宏定義,因此它如何作爲有效表達式存在我的代碼?是否有某種宏觀參數的正常規則暫停?我一直無法找到這個非Lisp'er可以理解的解構形式語法的定義。

+1

我錯過了一個事實,即GET是一個宏。在下面的答案中解釋... – edoloughlin 2010-11-03 16:53:54

回答

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之一。我不確定哪一個可以成爲一個規範的學習地點。

我不會假裝知道在底層引擎下該地圖究竟具有什麼功能,但我認爲它會將它引入let或類似的東西,就像我上面演示的那樣。 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

解構發生綁定表單中,並在地圖解構了var被束縛在左邊,關鍵是在右邊:

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

的Compojure正在做一個綁定形式幕後,所以你在上面使用該地圖拆解的形式有效地轉變成類似:

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

request是隱含提供的地圖。

矢量版本(例如,[some_arg])是一種替代方法,它只是綁定在請求中包含的地圖上。