2012-01-03 45 views
7

Xin lỗi cho danh hiệu khủng khiếp mơ hồ :)Clojure - Trích dẫn Lẫn lộn

Tôi mới vào macro và đang gặp khó khăn tìm hiểu sự khác biệt giữa hai báo cáo:

`(+ 1 2 ~(+ 2 3)) ; => (clojure.core/+ 1 2 5) 
'(+ 1 2 ~(+ 2 3)) ; => (+ 1 2 (clojure.core/unquote (+ 2 3))) 

Khi tôi chạy chúng mà không có sự unquote , họ có vẻ giống hệt hơn là đủ điều kiện?

`(+ 1 2 (+ 2 3)) ; => (clojure.core/+ 1 2 (clojure.core/+ 2 3)) 
'(+ 1 2 (+ 2 3)) ; => (+ 1 2 (+ 2 3)) 

Vì vậy, về cơ bản tôi bị nhầm lẫn bởi `vs '. Sự hiểu biết của tôi là cả hai đều trích dẫn mọi thứ trong danh sách, đó là lý do tại sao tôi không chắc tại sao unquoting lại hành xử khác nhau. Về cơ bản `cư xử theo cách tôi mong đợi cả hai` và 'để hành xử.

Cảm ơn!

Trả lời

10

Câu trả lời ngắn gọn là, việc hủy đăng ký chỉ hoạt động bên trong backquote. Trong một biểu thức được trích dẫn bình thường, mọi thứ - bao gồm ~ và mọi thứ bên trong/phía sau - chỉ được truyền như là, trong khi bên trong một biểu thức backquoted, mọi thứ bên trong/sau ~ được đánh giá (nhưng mọi thứ khác vẫn chưa được đánh giá). Vì vậy, không, không phải mọi thứ bên trong một biểu thức backquoted vẫn chưa được đánh giá - bạn có thể sử dụng ~ bên trong nó, để sử dụng nó như là một loại mẫu, nơi bạn "điền vào chỗ trống" với ~.

Edit: Để trích dẫn (ý định chơi chữ) các documentation liên quan đến câu hỏi của bạn:

Trích:

Quote (') 
'form => (quote form) 

và (từ phần special forms):

(hình thức báo giá) Sử dụng dạng chưa được đánh giá.

user=> '(a b c) 
(a b c) 

Lưu ý không có nỗ lực thực hiện để gọi hàm a. Giá trị trả về là danh sách gồm 3 ký hiệu.

Cú pháp-quote (còn gọi là quasiquote, backquote):

Đối Lists/Vectors/Sets/Maps, cú pháp-quote thiết lập một bản mẫu của cấu trúc dữ liệu tương ứng. Trong khuôn mẫu, các biểu mẫu không đủ tiêu chuẩn hoạt động như thể được trích dẫn theo cú pháp, nhưng các biểu mẫu có thể là được miễn trích dẫn đệ quy bằng cách loại trừ chúng bằng cách bỏ dấu hoặc nối kết không theo yêu cầu, trong trường hợp đó chúng sẽ được coi là biểu thức và được thay thế bằng mẫu theo giá trị của chúng hoặc chuỗi giá trị, tương ứng là .

+1

Bạn cũng có thể đề cập đến giấy lớn [Báo giá Quasi trong Lisp bởi Alan Bawden] (http://www.scribd.com/doc/47702904/Bawden-Quasi-Quotation-in-Lisp). – Daimrod

+0

Daimrod, vâng, cảm ơn vì liên kết! (Lưu ý cho người mới bắt đầu: Có một vài khác biệt giữa các phương ngữ Lisp và Clojure khác. Ví dụ, trong CL và giấy, ',' (khoảng trắng trong Clojure) được sử dụng để unquoting. Ngoài ra, trong CL, một ',' bên ngoài một biểu thức backquoted là không hợp lệ (thường là một lỗi đọc).) – danlei

+0

Cảm ơn, tôi đã không nhận ra unquoting được dành riêng cho cú pháp-quote. Điều đó chắc chắn giải thích kết quả. Tôi đang trải qua Joy of Clojure và tôi đã tạm dừng trong chương Macro để thử nghiệm và cố gắng hiểu công cụ này, vì vậy có thể tôi đã bỏ lỡ các giải thích thêm trong chương :) – anonymous

4

Thử chạy eval trên kết quả của hai biểu thức đầu tiên của bạn. Cái đầu tiên, với `, 'mở rộng" thành (+ 1 2 3), cái mà độc đáo đánh giá là 6. Thứ hai, với', "mở rộng" thành (+ 1 2 (unquote (+ 1 2))) và unquote không hợp lệ trong ngữ cảnh đó vì bạn không còn nằm trong dấu ngoặc kép nữa! Vì vậy, điều này hoàn toàn không đánh giá ở tất cả.

Về cơ bản có hai sự khác biệt giữa 'và `:

  • ' namespace-đủ điều kiện tất cả mọi thứ
  • 'cho phép unquoting