2012-09-10 23 views
10

Với vĩ mô bên dưới -gì ~' ngụ ý rằng khi thêm vào như là một tiền tố cho một biến trong vĩ mô

(defmacro defhello [fn-name body] `(defn ~fn-name [~'name] ~body)) 

và một chức năng được xác định khi gọi là -

(defhello lời chào (str " Xin chào" tên))

và gọi là

(chúc mừng "Joe")

, sẽ trở lại

Hello Joe

Tôi không hiểu việc sử dụng ~' ở phía trước của tên tham số? Nó làm gì? Không trích dẫn (') và unquote (~) hủy bỏ nhau? Điều gì xảy ra khi chúng được sử dụng cùng nhau? Tại sao không chỉ viết tên mà không có chúng?

+0

Ví dụ này đến từ đâu? –

+0

Tôi đã viết nó. Nó hoạt động như mong đợi. Tuy nhiên, ~ 'chỉ là thử và sai, vì vậy muốn biết tại sao nó hoạt động. – murtaza52

Trả lời

8

Tóm lại, các ~ đánh giá biểu thức trong biểu mẫu được trích dẫn cú pháp giống như nó cho ~fn-name. Trong trường hợp này, biểu thức để đánh giá là 'name, trong đó kết quả là biểu tượng không đủ tiêu chuẩn name.

Tuy nhiên, hãy chia nhỏ từng phần này một lần.

Nếu bạn chỉ có biểu tượng không đủ tiêu chuẩn name, nó sẽ được đánh giá là clojure.core/name khi chạy . Điều này sẽ dẫn đến một hình thức defn không chính xác và gây ra một ngoại lệ trình biên dịch.

(defn greeting [clojure.core/name] (str "Hello" name)) 

Nếu bạn chỉ có biểu tượng không đủ tiêu chuẩn được trích dẫn 'name, nó sẽ vẫn được đánh giá khi chạy. Sự khác biệt là nó sẽ mở rộng đến (quote clojure.core/name). Một lần nữa, điều này sẽ dẫn đến một hình thức defn không chính xác và gây ra một ngoại lệ trình biên dịch.

(defn greeting [(quote clojure.core/name)] (str "Hello" name)) 

Cuối cùng, bằng cách sử dụng ~'name, bạn sẽ có dạng trích dẫn đánh giá tại thời gian biên dịch, kết quả là biểu tượng không đủ tiêu chuẩn name, để lại cho bạn một hình thức thích hợp defn.

(defn greeting [name] (str "Hello" name)) 

1 - Điều này đúng cho ví dụ này bởi vì nó giả định khác name chức năng không tồn tại.

+0

1) Tại sao nó đánh giá các biểu tượng cho clojure.core/name ns, và không phải là ns hiện tại? Đây có phải là hành vi mặc định cho tất cả độ phân giải biểu tượng không? – murtaza52

+0

Cũng nhờ có câu trả lời tuyệt vời, nó rất hữu ích! – murtaza52

+1

Nó không. Nó đánh giá ký hiệu 'name' thành' clojure.core/name' vì hàm đó đã tồn tại và nằm trong phạm vi. ('clojure.core' được cung cấp theo mặc định.) Ngoài ra, dấu nháy đơn không bao gồm không gian tên đủ điều kiện, trong khi cú pháp-trích dẫn có. – Jeremy

2

Khi tôi hiểu nó, bạn trích dẫn định nghĩa hàm, do đó, nó sẽ không được đánh giá khi macro được xác định. Bạn sử dụng toán tử unquote ~ để đánh giá tên trong định nghĩa. Nếu tên là một loại danh sách [email protected] (unquote splice) sẽ đánh giá các yếu tố của một danh sách mà không có dấu ngoặc xung quanh.

1

Trích dẫn trước tên được sử dụng để giữ cho biểu tượng không đủ điều kiện.

Nếu bạn không biết những gì đủ điều kiện, vui lòng tham khảo Reader.

Ngoài ra, bạn có thể sử dụng macroexpand để gỡ lỗi macro.

Và nếu bạn muốn biết thêm về macro, tôi khuyên bạn nên đọc On Lisp. Có thể hơi khó, nhưng điều đó cho bạn biết cách macro hoạt động.

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