我本以为这会起作用:
(defun list-of-things (thing1 thing2 thing3)
"returns a ???"
'(thing1 thing2 thing3))
Run Code Online (Sandbox Code Playgroud)
但这实际上是返回列表所需的:
(defun list-of-things (thing1 thing2 thing3)
"returns a list"
(list thing1 thing2 thing3))
Run Code Online (Sandbox Code Playgroud)
这是两个不同的东西,也是 Lisp 语言的核心概念。
该语法'(a b c)是 的简写形式(quote (a b c)),quote是一种返回其参数unevaluated 的特殊形式。在这种情况下,它将是包含三个符号的列表。
另一方面,list是一个普通函数,它计算其参数并返回其值的列表。
更深入一点:在计算任何表达式之前,必须先阅读代码。Lisp 特有的部分(事实上,Common Lisp 更是如此)是“解析器”实际上只是一个 Lisp 函数,返回 Lisp 对象。然后将这些对象交给“评估器”,评估器对它们进行评估:
'(thing1 thing2 thing3),读取器知道这'是一个读取器宏,因此它读取(quote (thing1 thing2 thing3))。这是一个包含两个元素的列表,一个符号,另一个包含三个符号的列表。然后将该列表提供给求值器:它知道这是一种特殊形式,返回未求值的参数,因此它仅返回读者提供给它的quote列表。(thing1 thing2 thing3)(list thing1 thing2 thing3),阅读器还将其作为列表读取(这次包含 4 个符号),然后将其提供给评估器。现在,求值器看到第一个符号是list,一个函数,因此它评估参数(即它确定符号thing1... 绑定到什么),将它们传递给函数list,等等。所有这一切都是可能的,因为 Lisp代码是根据 Lisp对象(例如列表等)定义的。在“解析”(实际上称为读取)阶段之后,评估器实际上得到了一个实际的 Lisp 对象来评估。当谈论编译等时,事情当然会稍微复杂一些,但总体思路是相同的。运算quote符(缩写为')是一种“直接”访问读者创建的事物并“绕过”评估的方法。