Trong nhiệm vụ của tôi để hiểu đầy đủ các macro lisp mạnh mẽ như vậy, một câu hỏi xuất hiện trong đầu tôi. Tôi biết rằng quy tắc vàng về macro là một quy tắc "Không bao giờ sử dụng macro khi chức năng sẽ thực hiện công việc". Tuy nhiên đọc Chương 9 - Practical: Building a Unit Test Framework - từ cuốn sách Thực hành chung Lisp Tôi đã được giới thiệu với macro dưới đây có mục đích là để loại bỏ sự trùng lặp của biểu thức trường hợp thử nghiệm, với nguy cơ bị gắn nhãn sai kết quả.Lisp: Macros vs Chức năng
;; Function defintion.
(defun report-result (result form)
(format t "~:[FAIL~;pass~] ... ~a~%" result form))
;; Macro Definition
(defmacro check (form)
`(report-result ,form ',form))
OK, tôi hiểu mục đích của nó nhưng tôi có thể thực hiện nó bằng cách sử dụng chức năng thay vì một vĩ mô, ví dụ:
(setf unevaluated.form '(= 2 (+ 2 3)))
(defun my-func (unevaluated.form)
(report-result (eval unevaluated.form) unevaluated.form))
- là chỉ này có thể bởi vì vĩ mô nhất định là quá đơn giản ?
- Hơn nữa, Hệ thống Macro Lisp có mạnh mẽ như vậy đối thủ tương đối do mã của nó - giống như cấu trúc điều khiển, chức năng, vv - được biểu diễn như một DANH SÁCH?
"Quy tắc vàng" này là ngu ngốc. Sử dụng macro bất cứ nơi nào bạn tìm thấy chúng phù hợp và quên đi tất cả các "quy tắc" não bị hư hại. Đối với ví dụ của bạn, nó không phải là gần như một tương đương, kể từ khi bạn đang trì hoãn một trình biên dịch để chạy. Nếu form của bạn chứa các tham chiếu đến một số tên scoped cục bộ thì nó sẽ không hoạt động. –
Sk, bạn có thể đưa ra một ví dụ về hàm eval và tên phạm vi cục bộ không? – utxeee
'(let ((x 2)) (eval '(+ x x)))' đơn giản sẽ không hoạt động, OTOH nếu biểu mẫu '(+ x x)' này được tạo ra bởi một macro nó sẽ được biên dịch tự nhiên. –