【发布时间】:2012-07-20 16:26:15
【问题描述】:
为了完全理解如此强大的 lisp 宏,我想到了一个问题。我知道关于宏的一条黄金法则是:“当函数可以完成工作时,切勿使用宏”。 然而,阅读第 9 章 - Practical: Building a Unit Test Framework - 来自 Practical Common Lisp 一书,我被介绍到下面的宏,其目的是消除测试用例表达式的重复,以及随之而来的错误标记结果的风险。
;; Function defintion.
(defun report-result (result form)
(format t "~:[FAIL~;pass~] ... ~a~%" result form))
;; Macro Definition
(defmacro check (form)
`(report-result ,form ',form))
好的,我理解它的目的,但我可以使用函数而不是宏来完成它,例如:
(setf unevaluated.form '(= 2 (+ 2 3)))
(defun my-func (unevaluated.form)
(report-result (eval unevaluated.form) unevaluated.form))
- 这仅仅是因为给定的宏太简单了吗?
- 此外,由于代码本身(如控制结构、函数等)被表示为 LIST,Lisp 宏系统相对于它的对手来说是否如此强大?
【问题讨论】:
-
这条“黄金法则”很愚蠢。在你认为合适的地方使用宏,忘记所有脑残的“规则”。至于您的示例,它几乎不是等效的,因为您将编译推迟到运行时。如果您的表单包含对某些本地范围名称的引用,则它根本不起作用。
-
Sk,你能举一个关于 eval 函数和本地范围名称的例子吗?
-
(let ((x 2)) (eval '(+ x x)))根本不起作用,OTOH 如果这个(+ x x)表单是由宏生成的,它会自然编译。 -
这个 qst 首先出现在 google 搜索中,但它并没有真正解释 Lisp 宏和函数之间的区别。似乎问题主题行可以写得更好。 JMO。
标签: macros common-lisp