“lisp form”的定义是什么?

30

“Lisp形式”的定义是什么?

据我所知,它是“一个原子或一个列表,该列表的第一个元素是一个符号”。

但是,在Scheme中,以下内容不会被视为形式:

((lambda () 42))  ;; The answer to Life, the Universe and Everything.
因为列表的第一个元素本身就是另一个列表。在它被求值之后,它将成为一个过程(而不是符号)。
我可以找到几个不同的网站和教程来讲解 Lisp 表达式,但没有一个给出完整详细的定义。我在哪里能找到一个呢?

4
这实际上是一个有效的Lisp表达式和程序。我想我的下面的定义将会尽可能详细,不确定是否漏掉了什么,但我相信它是全面的。 - Zorf
在Clojure中:((fn [] 42)) - David Tonhofer
2个回答

54

Lisp表达式是Lisp数据的一种形式,也是一段程序,可以在不出错的情况下进行求值。

(3 4 1)

这是一个Lisp数据,它是包含3、4和1的列表。但是它不是一种表达形式,因为尝试对其进行求值不会得到另一个数据,而是会导致错误。

3

“数据元”和“表单”,也称为“正常形式”或“自我评估数据元”,它的计算结果等于它本身。

(+ 3 4 1)

这是一个 复合形式,对其求值的结果是 标准形式 8

除了标准形式和复合形式以外,复合形式还可以细分为过程调用和特殊形式(也称语法),但更恰当地说,特殊形式的头部是语法,例如:

(if (oddp 2) (print "me") (print "or me"))

这是一种特殊的形式,因为它的头部是语法而不是过程。 过程调用和特殊形式之间唯一的区别是,过程调用将形式中的所有参数视为自身的形式,并尝试首先对其进行求值,而特殊形式则不一定如此。 例如,根据我们的理解,在这个复合形式中只有第二个和第四个成员被求值,第一个成员是语法,第三个成员在这种情况下被丢弃。

((a 1) (b 2))

在Common Lisp中,不是一个表单(form),但如果表单(a 1)评估为过程数据(procedure datum),则它可以成为Scheme中的有效表单。因此:

(let ((a 1) (b 2)) (+ a b))

let是一种特殊形式,它不会评估其第二个参数,并以与非特殊形式不同的方式评估其第三个参数。也就是说,在其第三个形式中作为子形式的a和b具有不同的绑定关系。let在此情况下是一个表示特殊形式的语法关键字。

请注意,特殊形式仍然可能评估其所有参数,但它们不是过程调用,因为它们的头部是语法,而过程可以作为参数传递给其他函数,语法不能。

(func arg1 #'let)

同样也是一个错误:

(funcall let ((a 1) (b 2)) (+ a b))

这是一个错误,表明它与过程调用不同。


你如何声明自己的 if 表单?你能否举一个 my-if 表单的语法示例? - eliocs
1
很抱歉,“lisp datum”不是正确的术语,因为在Lisp中,“datum”的定义是“一个a-list是一对列表,一对的car被称为键,cdr被称为datum”,来自于《Common Lisp第二版》的第431页。 - prosseek
点赞明确引用特定类型的表单。 - dat
有人可能会认为if不是语法,而是一个要求解释器执行惰性评估的函数(尽管出于性能、简单性和确定性的原因,特别是对于副作用,它通常不会这样做)。但让我们保持实际。 - David Tonhofer
'form' 和 'expression' 有区别吗?我的意思是所有形式都有值,即使为 nil,是吗? - oskarkv

14

来自Common Lisp Hyperspec词汇表

form n. (表达式) 1. 任何旨在被求值的对象。2. 符号、复合形式或可自求值对象。3. (对于操作符,例如<<operator>> form''),指以该操作符为第一个元素的复合形式。引用表达式是一种恒定表达式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接