2011-10-17 27 views
5

Tôi định nghĩa một hàm, có hai tham số - ánh xạ và một khóa. Điều quan trọng là tham khảo từ các tham số bản đồ phân hủydefn vs let liên quan đến sự phân hủy

(defn myfunc [{v k} k] 
    v) 

khi tôi gọi:

(myfunc {:a 10} :a) 

Nó ngạc nhiên sản xuất dự kiến ​​kết quả: 10

điều tương tự trong các let:

(let [{v k} {:a 10} k :a] v) 

không thành công, vì k không được xác định tại thời điểm, khi phần đầu tiên được đánh giá.

Câu hỏi của tôi là: tại sao việc phân tách bên trong các tham số chức năng hoạt động khác so với phân tách trong các biểu thức cho phép?

Trả lời

3

Macroexpanding dạng defn tôi nhận được tương đương với này (thứ .withMeta lấy ra và định dạng lại):

(def myfunc 
    (fn* myfunc 
     ([p__11393 k] 
      (let* [map__11394 p__11393 
       map__11394 (if (seq? map__11394) 
           (apply hash-map map__11394) 
           map__11394) 
       v   (get map__11394 k)] 
       v)))) 

Vì vậy, ở đây chúng ta có thể thấy rằng bản đồ {v k} là trong thực tế đầu tiên được gán cho một biến địa phương p__11393. Sau đó, các bài kiểm tra tuyên bố if nếu biến đó thực tế là một chuỗi và biến nó thành một bản đồ băm nếu có, nếu không, hãy để nguyên nó. Quan trọng hơn, giá trị được gán cho k được tra cứu trên bản đồ sau tất cả điều này xảy ra, do đó điều này không có lỗi (và cũng có thể nếu :a không có trong bản đồ, get trả về nil trong trường hợp đó).

Mặt khác macroexpanding dạng let tôi nhận được

(let* 
    [map__11431 
    {:a 10} 
    map__11431 
    (if (seq? map__11431) (apply hash-map map__11431) map__11431) 
    v 
    (get map__11431 k) 
    k 
    :a] 
    v) 

và ở đây chúng ta có thể thấy rằng v được kết quả của (get map__11431 k), nhưng k không được xác định vào thời điểm này chưa, vì thế mà lỗi.

+0

bây giờ câu hỏi là, nếu chênh lệch đó đã được coi là một lỗi hoặc như là một tính năng ... – aav

+0

tôi sẽ nói nếu người ta biết rằng sự phá hoại xảy ra bên trong cơ thể của hàm, nó không đáng ngạc nhiên, do đó không phải là lỗi. Nhưng tôi nghĩ rằng thực tế này có thể được giải thích tốt hơn ở những nơi thích hợp - nếu tôi nhớ chính xác Niềm vui của Clojure, chẳng hạn, không thực sự hiểu được điều này. – Paul

+0

điều thú vị (nhưng không đáng ngạc nhiên) là anh ta sẽ không làm việc: (defn myfunc [{v k} {k: k1}] v) – aav

0

Đây không phải là một câu trả lời hoàn chỉnh, nhưng sau không làm việc:

user=> (defn myfunc [{v k} k] v) 
#'user/myfunc 
user=> (myfunc {:a 10} :a) 
10 
user=> (let [k :a {v k} {:a 10}] v) 
10 
user=> 
+0

điều này sẽ làm việc, bởi vì * k * được định nghĩa trước bất cứ điều gì khác – aav

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