Tôi đang tìm hiểu về macro Clojure và các ví dụ mã đôi khi sẽ có cấu trúc '~symbol
hoặc luân phiên ~'symbol
. Tôi biết rằng (quote
và '
ngăn không cho một biểu mẫu được đánh giá và backquote bổ sung thêm tiêu chuẩn không gian tên và điều đó tạo ra một biểu mẫu được trích dẫn để được đánh giá. Câu hỏi của tôi là: tại sao nó hữu ích để dừng lại sau đó bắt đầu đánh giá? Tôi cũng giả định rằng ~'symbol
và '~symbol
là khác nhau, nhưng làm thế nào?Mục đích của ~ 'hoặc' ~ trong Clojure là gì?
Trả lời
~'symbol
được sử dụng để tạo ra một biểu tượng không đủ tiêu chuẩn. Các macro của Clojure nắm bắt không gian tên theo mặc định, do đó, một biểu tượng trong macro thường được giải quyết thành (your-namespace/symbol)
. Thành ngữ báo giá không được trích dẫn trực tiếp dẫn đến tên biểu tượng đơn giản, không đủ tiêu chuẩn - (symbol)
- bằng cách đánh giá biểu tượng được trích dẫn. Từ The Joy Of Clojure:
(defmacro awhen [expr & body]
`(let [~'it ~expr] ; refer to the expression as "it" inside the body
(when ~'it
(do [email protected]))))
(awhen [:a :b :c] (second it)) ; :b
'~symbol
có thể được sử dụng để chèn tên trong macro hoặc tương tự. Tại đây, symbol
sẽ bị ràng buộc với một giá trị - let [symbol 'my-symbol]
. Giá trị này sau đó được chèn vào mã mà macro tạo ra bằng cách đánh giá symbol
.
(defmacro def-symbol-print [sym]
`(defn ~(symbol (str "print-" sym)) []
(println '~sym))) ; print the symbol name passed to the macro
(def-symbol-print foo)
(print-foo) ; foo
~
là macro trình đọc cho hàm unquote
. trong một danh sách trích dẫn nó gây ra một biểu tượng được đánh giá khá sau đó được sử dụng như một biểu tượng văn chương
user> (def unquoted 4)
user>`(this is an ~unquoted list)
(user/this user/is user/an 4 clojure.core/list)
user>
tất cả mọi thứ ngoại trừ các biểu tượng không thể viện chứng được sử dụng giống như một biểu tượng mà không thể viện chứng đã được giải quyết để giá trị của nó 4. đây là nhất thường được sử dụng trong các macro viết. Các repl cũng in không gian tên (người dùng) trước mặt của tên khi nó được in danh sách kết quả.
nhiều macro, về cơ bản chỉ là các mẫu được thiết kế để thực hiện một loạt các biến thể nhỏ về một thứ không thể thực hiện được trong một hàm. Trong ví dụ này, một macro mẫu định nghĩa một hàm bằng cách tạo ra một cuộc gọi đến def. cú pháp-quote với unquoting làm cho điều này dễ dàng hơn nhiều để đọc:
user> (defmacro def-map-reducer [name mapper reducer]
`(defn ~name [& args#]
(reduce ~reducer (map ~mapper args#))))
#'user/def-map-reducer
user> (def-map-reducer add-incs inc +)
#'user/add-incs
user> (add-incs 1 2 3 4 5)
20
so với:
user> (defmacro def-map-reducer [name mapper reducer]
(let [args-name (gensym)]
(list `defn name [`& args-name]
(list `reduce reducer (list `map mapper args-name)))))
#'user/def-map-reducer
user> (def-map-reducer add-decs dec +)
#'user/add-decs
user> (add-decs 1 2 3 4 5)
10
user>
trong ví dụ thứ hai tôi cũng không sử dụng tính năng tự động gensyms đặc trưng bởi vì tôi không ở cú pháp-trích dẫn
Vì vậy, tôi biết tại sao tôi muốn sử dụng ~ trước biểu tượng trong danh sách mà trước đây tôi đã trích dẫn, câu hỏi của tôi là lý do tại sao tôi sử dụng ~ 'hoặc' ~ ngay bên cạnh nhau. – Alex
hy vọng ví dụ này sẽ cho thấy động lực tốt hơn, nhờ phản hồi :) –
- 1. mục đích là gì? "::" trong
- 2. Mục đích của Rake là gì?
- 3. Mục đích của Parse Vexing là gì?
- 4. Mục đích của tệp .edmx là gì?
- 5. Mục đích của character_set_connection là gì?
- 6. Mục đích của is_uploaded_file() là gì?
- 7. Mục đích của thuộc tính-đích là gì?
- 8. Mục đích của thư mục buildSrc của gradle là gì?
- 9. mục đích thực tế của các vars và ràng buộc năng động của clojure là gì?
- 10. JAF là gì? Mục đích của nó là gì?
- 11. Mục đích của tệp pdb là gì?
- 12. Mục đích của tệp vshost.exe là gì?
- 13. Mục đích của layout.xml là gì?
- 14. Mục đích của `__metaclass__ = type` là gì?
- 15. Mục đích của String.IsInterned là gì?
- 16. Mục đích của __cxa_pure_virtual là gì?
- 17. Mục đích của HttpHeaders.TryAddWithoutValidation là gì?
- 18. Mục đích của ldexp là gì?
- 19. Mục đích của IntentSender là gì?
- 20. Mục đích của requestWindowFeature() là gì?
- 21. Mục đích của nguyên mẫu là gì?
- 22. Mục đích của lớp Expression là gì?
- 23. Mục đích của startManagingCursor là gì?
- 24. Mục đích của config.assets.precompile là gì?
- 25. Mục đích của UIWindow là gì?
- 26. Mục đích của phiên JMS là gì?
- 27. Mục đích của Array.GetLowerBound (int) là gì?
- 28. Mục đích của 'var' là gì?
- 29. mục đích của Thread.holdsLock (khóa) là gì?
- 30. Tệp xcscheme là gì? Mục đích của nó là gì?
:) Cảm ơn bạn, điều đó có ý nghĩa. – Alex
vẫn còn một điểm mà vẫn chưa rõ ràng với tôi: '(unquote (quote user/foo))' kết quả trong 'foo' thay vì' user/foo', khi nào và như thế nào nó xảy ra rằng không gian tên bị tước đi? Làm thế nào là nó phù hợp với hành vi "bình thường" của 'unquote' mà đánh giá các hình thức sau đây? – skuro
Ví dụ đầu tiên không hoạt động. Nó sẽ là '\' (để [~ 'it ~ expr] ... ' – Ming