2010-11-03 52 views
6

Tôi nghĩ tôi sẽ đăng bài này khi tôi làm cho nó hoạt động thông qua phỏng đoán mà không có sự hiểu biết thực sự về những gì đang xảy ra và tôi nghĩ nó có thể hữu ích nếu ai đó giải thích.Hình thức hủy cấu trúc và tính năng Soạn thảo?

Tôi hiểu làm thế nào để có được một yếu tố của: params bản đồ trong một handler Compojure:

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

hoặc

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

mặc dù tôi không hoàn toàn hiểu những gì các phần {some_arg "some_arg"} đang làm :(

Tôi cũng muốn truy cập phần :remote-addr của yêu cầu cũng như some_arg. Và tôi đã kết thúc bằng

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

Vì vậy, tôi nhận được rằng các dây không thể viện chứng some_argip là tên của các biến mà tôi muốn các giá trị ràng buộc nhưng bản đồ trên không phải là một bản đồ có giá trị Clojure. Làm thế nào nó hoạt động?

Tôi cũng nhận được rằng điều này được đánh giá dựa trên bản đồ yêu cầu Ring (được cung cấp bởi macro defroutes) nhưng biểu thức ở trên không phải là hàm hoặc định nghĩa macro sao cho nó có thể tồn tại như một biểu thức hợp lệ ma cua toi? Có một số loại đình chỉ của các quy tắc bình thường cho các đối số vĩ mô? Tôi đã không thể tìm thấy một định nghĩa cú pháp của các hình thức destructuring comprehensible này không Lisp'er.

+1

Tôi đã bỏ lỡ thực tế GET là macro. Giải thích trong câu trả lời dưới đây ... – edoloughlin

Trả lời

3

Bản đồ là bản đồ phá hoại hợp lệ. Ở bất kỳ nơi nào bạn liên kết tên, bạn có thể sử dụng destructuring. Bạn có thể làm điều tương tự trong một let, như thế này:

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

Tôi đã viết một bài về destructuring bản đồ trong bối cảnh các đối số được đặt tên, nhưng nó áp dụng ở đây. Bạn có thể thấy điều này hữu ích: Clojure - named arguments

rất nhiều bài đăng trên blog thể hiện phá hoại, bao gồm this một. Tôi không chắc cái nào sẽ là nơi kinh điển để học hỏi.

Tôi không giả vờ biết chính xác những gì compojure làm với bản đồ đó dưới mui xe, nhưng tôi đoán nó ném nó trong một let hoặc một cái gì đó tương tự như tôi đã chứng minh ở trên. GET là một macro, do đó, nó không phải đánh giá bản đồ bạn vượt qua nó, đó là lý do tại sao bạn sẽ không nhận được một lỗi trừ khi nó đánh giá nó.

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) 

Dưới mui xe, phép thuật xảy ra với bản đồ đó và nó được chuyển đến một hàm gọi là phá hủy ma thuật phá hủy.

Không có bất kỳ điều gì đặc biệt xảy ra ở đây ngoài biểu mẫu macro/đặc biệt bình thường và đánh giá trễ.

1

huỷ diễn ra trong một hình thức ràng buộc, và cho bản đồ destructuring var bị ràng buộc là ở bên trái, và quan trọng là ở bên phải:

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

Compojure đang làm một hình thức ràng buộc đằng sau hậu trường , do đó hình thức bản đồ destructuring bạn đang sử dụng trên là một cách hiệu quả biến thành một cái gì đó như:

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

đâu request là một bản đồ ngầm cung cấp.

Phiên bản vectơ (ví dụ: [some_arg]), là một thay thế chỉ liên kết với bản đồ :params có trong yêu cầu.

Các vấn đề liên quan