Lisp 如何知道函数是否计算其参数?

Lisp 如何知道函数是否计算其参数?,lisp,common-lisp,evaluation,clisp,Lisp,Common Lisp,Evaluation,Clisp,如何知道函数是否计算其参数 Setq似乎没有评估它的参数,而是 Break 15 [16]> (setq j (kjl klj)) *** - EVAL: undefined function KJL 那么评估什么时候完成 cond和和似乎也不评估它们的参数,但 Break 18 [19]> (cond ((eql nil nil) (write "lkj"))) "lkj" "lkj" Break 18 [19]> (cond ((eql nil (not nil)) (w

如何知道函数是否计算其参数

Setq似乎没有评估它的参数,而是

Break 15 [16]> (setq j (kjl klj))
*** - EVAL: undefined function KJL
那么评估什么时候完成

cond
似乎也不评估它们的参数,但

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)
才能知道它是否正确,不是吗?

理论: 功能 运行库在将参数传递给(例如)之前对其进行评估

例如,当您编写
(eql a 1)
时,函数
eql
获取变量
a
的值和本身的文本
1
的值

宏 运行时不计算的参数(如and)。 宏将其参数转换为代码,然后由运行时进行计算

例如,当您编写
cond((eql nil nil)(write“lkj”))
时,它会扩展为如下内容:

> (macroexpand '(cond ((eql nil nil) (write "lkj"))))
(IF (EQL NIL NIL)
    (PROGN (WRITE "lkj"))
    NIL)
然后将表单作为特殊操作符根据其规范进行评估

当然,您不想实际阅读的宏扩展来了解它的功能-您需要阅读文档。但是,您确实可以使用调试自己的宏

特种作业人员 运行时处理(例如),好的,特别的,也就是说,行为对于每个特殊的操作符来说是特殊的

例如,当您编写
(setq a(!4))
时,运行时不会计算
a
,但会计算
(!4)
,它会发现
绑定到函数,因此它计算
4
(it),然后调用
的函数绑定4
,并将返回值(
24
)赋给变量
a

命令 实际上,正如@Paulo在评论中提到的,首先检查符号是否为特殊运算符(因为实现可以将宏实现为特殊运算符和vv);它不能同时是宏和函数(但可以使用)。但这超出了这个问题的范围

实践:使用CLHS 在Emacs中编辑代码,加载并查看您感兴趣的符号的文档。
do将立即说明符号的定义。

函数始终计算其参数<但是,code>setq
cond
不是函数
setq
是一种特殊形式,而
cond
是一个宏。所有函数都对其所有参数进行求值。要了解一门语言,你需要了解它们的特殊形式和核心程序。此外,了解和使用命名约定甚至在阅读文档之前就为lispers提供了线索。CL中没有“原语”的概念。这是它的一个优点:你可以按照自己喜欢的方式构建语言基础,自己决定什么是原语。@sds没有“原语”,但正如你在回答中所解释的,有专门的操作员。您至少需要一些特殊运算符来实现一种有用的语言;没有他们,你无法真正建立基础。谢谢你详细的回答!除了quote之外,您还知道其他不计算其参数的常用原语吗?不客气!我不知道你说的“原始”是什么意思。如果单击我的答案中的链接,您会发现第3.1.2.1.2.1节列出了图3-2中常见的Lisp特殊运算符
psetq
setq
计算它们的偶数参数,而不是奇数参数……因此,询问“除了引号以外的其他不计算它们的参数的公共原语”并不是一件很有意义的事情。想想你想做什么,CL如何帮助你,而不是CL提供什么功能。CL标准有~1k个符号(这只是标准——任何实现都会带来至少同样多的扩展)。我正在为诅咒编写一个lisp解释器,教授要求实现3个不评估其参数的原语,这就是为什么我要问这个问题。啊。。。好的,试试
quote
setq
,如果
,这些都足够多样化和重要;我想你的教授会喜欢这个选择:-)