Tôi muốn chứng minh sự thiếu hiểu biết của mình bằng một ví dụ.
Sử dụng hai định nghĩa vĩ mô sau đây,
(defmacro for (var from init to final do &rest body)
"Execute a simple for loop: (for i from 1 to 10 do (print i))."
(let ((tempvar 'max))
`(let ((,var ,init)
(,tempvar ,final))
(while (<= ,var ,tempvar)
,@body
(setq ,var (1+ ,var))))))
(defmacro for (var from init to final do &rest body)
"Execute a simple for loop: (for i from 1 to 10 do (print i))."
(let ((tempvar (make-symbol "max")))
`(let ((,var ,init)
(,tempvar ,final))
(while (<= ,var ,tempvar)
,@body
(setq ,var (1+ ,var))))))
macro đầu tiên che mờ bất kỳ biến nào có tên max
xảy ra trong cơ thể và biến thứ hai thì không, có thể được hiển thị với ví dụ sau:
(let ((max 0)) ;; this variable is shadowed if the first macro defintion is used
(for i from 1 to 3 do
(setq square (* i i))
(if (> square max)
(princ (format "\n%d %d" i square)))))
Theo như tôi đã học được việc đánh giá một cuộc gọi macro hoạt động như thế này:
Macro được đánh giá hai lần. Đầu tiên cơ thể được đánh giá và trả lại một hình thức. Hình thức này sau đó được đánh giá lại.
Càng xa càng tốt.
Nhưng nếu tôi cho rằng macro thực sự trả về một đoạn văn bản có thể là một dạng không thể thiếu, sau đó được giải thích, tôi nhận được một xung đột khiến tôi không thể hiểu được ví dụ trên.
Đoạn văn bản nào mà macro thứ hai sử dụng make-symbol
return, để không xảy ra hiện tượng đổ bóng? Theo hiểu biết của tôi, một tên biểu tượng được chọn ngẫu nhiên cực kỳ khó có thể có ý nghĩa.
Nếu tôi sử dụng pp-macroexpand...
cả hai macro trả lại cùng một bản mở rộng.
Có ai có thể giúp tôi thoát khỏi sự nhầm lẫn này?
print-gensym
và print-circle
cho t
bạn sẽ có thể thấy sự khác biệt trong các mở rộng macro.
#:max
. Điều đó nghĩa là gì ? Tôi rất quan tâm đến nhiều chi tiết hơn.
#:
chỉ là một quy ước của máy in để chỉ ra một biểu tượng không liên quan (đây là những gì được print-gensym
bật), có nhiều chi tiết hơn trong hướng dẫn sử dụng : (elisp) Creating Symbols
.