如何知道函数是否对其参数求值?
Setq 似乎不评估它的参数但是
Break 15 [16]> (setq j (kjl klj))
*** - EVAL: undefined function KJL
那么评估什么时候完成?
cond
和 and
似乎也没有评估他们的论点,但是......
Break 18 [19]> (cond ((eql nil nil) (write "lkj")))
"lkj"
"lkj"
Break 18 [19]> (cond ((eql nil (not nil)) (write "lkj"))
NIL
在上面的示例中,cond
必须评估 (eql nil nil)
才能知道它是否为真,不是吗?
最佳答案
理论:Form Evaluation
函数
运行时在将参数传递给 function 之前评估参数(例如 eql
)。
例如,当您编写 (eql a 1)
时,函数 eql
获取变量 a
的值和文字 1
本身。
宏
运行时不评估 macros 的参数(例如 cond
和 and
)。
宏将它们的参数转换为代码,然后由运行时评估。
例如,当您编写 cond ((eql nil nil) (write "lkj")))
时,它会扩展为如下内容:
> (macroexpand '(cond ((eql nil nil) (write "lkj"))))
(IF (EQL NIL NIL)
(PROGN (WRITE "lkj"))
NIL)
然后是 if
形式根据其作为特殊运算符的规范进行评估。
当然,您不想真正阅读 cond
的宏展开式了解它的作用 - 你阅读了文档。但是,您确实使用了 macroexpand
调试您自己的宏。
特殊运算符
运行时句柄 special operators (例如 setq
),好吧,特别,也就是说,每个特殊运算符的行为都是特殊的。
例如,当您编写 (setq a (! 4))
时,运行时不会评估 a
,但是,它会评估,计算 (!4)
,它发现 !
被绑定(bind)到一个函数,所以它计算 4
(它是 evaluates to itself),然后调用!
与参数 4
的函数绑定(bind),并将返回值 (24
) 分配给变量 a
。
订单
实际上,正如@Paulo 在评论中提到的,首先检查符号是否为特殊运算符(因为实现可以将宏实现为特殊运算符和 vv);它不能同时是一个宏和一个函数(但你可以使用 compiler macros )。这超出了这个问题的范围......
练习:使用 CLHS
在 Emacs 中编辑代码,加载 clhs.el , 并查看您感兴趣的符号的文档。 do 会立即说明符号定义为什么。
关于lisp - 如何知道函数是否评估其参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24998521/