如果您编写类似的东西(+ 2 3),则将+其视为函数,如果+没有与之关联的任何函数定义,则会发生错误.
如果你写的东西(let (a b c)),(a b c)读作数据.
lisp如何决定?
这里有两个基本的lisp概念:
读取是将文本转换为lisp对象的行为.诸如数字和列表之类的Lisp对象具有所谓的读取形式,这是一种可以读入对象的文本表示.它通常与打印格式相同.如果您来自Java等语言,toString()会提供对象的打印形式.没有相同的读取概念,因为Lisp具有有趣且强大的属性,Lisp源代码是一个lisp对象.
重要的是要注意阅读与评估不同,尽管许多对象都是自我评估的.例如,数字是一个在评估时返回自身的对象.更常见的是说许多表单都是自我评估的,但你应该记住,上下文中的"表单"通常与"lisp对象"同义,其含义是对象将被评估.
考虑在REPL中运行简单程序时会发生什么可能是有用的.回想一下,"REPL"代表"读取,评估,打印,循环",而Lisp是这些步骤之间的差异真正清晰的语言.
考虑列表程序:
161
Run Code Online (Sandbox Code Playgroud)
在REPL中运行它时,结果如下:
161
Run Code Online (Sandbox Code Playgroud)
这里发生的是以下内容:
符号的读取形式将是文本abc.符号评估它们所持有的变量.让我们abc在REPL中运行程序:
abc
Run Code Online (Sandbox Code Playgroud)
该程序实际上产生错误:
eval-last-sexp-1:符号作为变量的值为void:abc
这里发生的是:
特殊形式setq将符号设置为指向变量.更多关于以下内容.
从这里开始,Lisp就像大多数语言一样.调用(+ 1 (+ 2 3))将plus(1, plus(2,3))使用带有加号函数的命令式语言执行相同的操作.整个表达式将为红色以构建列表对象(+ 1 (+ 2 3 )),列表对象是三个元素的列表+,1以及列表(+2 3).然后,外+,作为一个函数调用,将导致解释评价的对象1,这是自我评估和(+ 2 3),这将最终评估为5.然后+将两个评价对象,1并且5,并将其添加和返回6.
但是,Lisp具有所谓的特殊形式.特殊表单可能会跳过评估步骤,只使用原始对象.例如,setq是一个评估第二个参数但不是第一个参数的特殊形式.
(setq a (+ 2 3))
Run Code Online (Sandbox Code Playgroud)
会不会评估符号"A",但将采取符号"A",并将其分配到什么(+ 2 3)计算结果为,即5号.然后,调用
a
Run Code Online (Sandbox Code Playgroud)
在REPL中将打印5.
所以回答原来的问题......"让"是一个特殊的形式,所以它的参数不会立即评估:)
宏也不评估他们的论点,但对原始问题可能没有必要进行全面讨论.