我正在研究Lisp。我遇到了两个术语“列表”和“S表达式”。我只是无法区分它们。它们只是Lisp中的同义词吗?
答案 0 :(得分:27)
首先,并非所有S表达式都代表列表;表示裸原子的表达式如foobar
也被认为是S表达式。与“cons cell”语法(car . cons)
一样,当“cons”部分本身不是另一个列表(或nil)时使用。更熟悉的列表表达式,例如(a b c d)
,只是嵌套cons单元链的语法糖;该示例扩展为(a . (b . (c . (d . nil))))
。
其次,术语“S表达式”是指语法 - (items like this (possibly nested))
。这样的S表达式是列表的Lisp源代码中的表示,但从技术上讲它本身并不是一个列表。这种区别与十进制数字序列及其数值之间的区别,或引号内的字符序列与结果字符串之间的区别相同。
这可能是一种过于技术性的区别;程序员通常会将值的文字表示称为值本身。但是使用Lisp和列表,事情变得有点棘手,因为Lisp程序中的所有在技术上都是一个列表。
例如,请考虑以下表达式:
(+ 1 2)
以上是一个简单的S表达式,它表示一个由原子+
,1
和2
组成的平面列表。
但是,在Lisp程序中,这样的列表将被解释为对+
函数的调用,其中1和2作为参数。 (请注意,这是列表,而不是 S-expression ,这是如此解释;评估者是已经由读者预先解析的列表,而不是源代码文本。)
因此,虽然上面的S表达式代表一个列表,但它很少会在Lisp程序的上下文中将称为作为“列表”。除非讨论宏,或者读者的内部工作,或者由于某些其他代码生成或解析上下文而进行了一次metasyntactic讨论,否则典型的Lisp程序员会将上述内容视为数字表达式。
另一方面,以下任何可能 的S表达式都将被称为“列表”,因为将它们作为Lisp代码进行评估将生成由上述文字S表达式表示的列表作为运行时值:
'(+ 1 2)
(quote (+ 1 2))
(list '+ 1 2)
当然,代码和数据的等价性是Lisp的一个很酷的东西,所以区别是流动的。但我的观点是,虽然以上所有都是S表达式和列表,但只有一些在随意的Lisp中被称为“列表”。
答案 1 :(得分:15)
S表达式是数据的表示法。
历史上 s-expression (符号表达式的缩写)被描述为:
FOO
和BAR
(
expression-1 .
expression-2 < / em> )
NIL
(
A
.
(
B
.
NIL
)
)
更简单地写为列表(A B)
另请注意,历史程序文本的编写方式不同。函数ASSOC
的示例。
assoc[x;y] =
eq[caar[y];x] -> cadar[y];
T -> assoc[x;cdr[y]]
历史上也存在从这些m表达式(元表达式的缩写)到s表达式的映射。今天,大多数Lisp程序代码都是使用s表达式编写的。
这里描述:McCarthy, Recursive Functions of Symbolic Expressions
在像Lisp这样的Lisp编程语言中, s-expressions 有更多的语法,可以编码更多的数据类型:
symbol123
,|This is a symbol with spaces|
123
,1.0
,1/3
,... "This is a string"
#\a
,#\space
#(a b c)
( a . b )
,(a b c)
; this is a comment
,#| this is a comment |#
等等。
<强>解释强>
列表是数据结构。它由cons单元和列表结束标记组成。列表在Lisp中有符号作为s表达式中的列表。您可以对列表使用其他一些表示法,但在Lisp中,已经确定了s-expression语法来编写它们。
旁注:程序和表单
在像Common Lisp这样的编程语言中,编程语言的表达式不是文本,而是数据!这与许多其他编程语言不同。编程语言Common Lisp中的表达式称为Lisp forms
。
例如,函数调用是Lisp数据,其中调用是一个列表,其中函数符号作为其第一个元素,下一个元素是其参数。
我们可以将其写为(sin 3.0)
。但它确实是数据。我们也可以构建数据。
评估Lisp表单的函数称为EVAL
,它接受Lisp数据,而不是程序文本或程序文本字符串。因此,您可以使用返回Lisp数据的Lisp函数构造程序:(EVAL (LIST 'SIN 3.0))
求值为0.14112
。
由于Lisp表单有一个数据表示,它们通常使用Lisp的外部数据表示来编写 - 这是什么? - s-expressions!
这是s表达式。 Lisp表单作为Lisp数据从外部写成s表达式。
答案 2 :(得分:5)
首先应该了解主要的Lisp功能 - 程序可以作为数据进行操作。与其他语言(如C或Java)不同,您使用特殊语法({
,}
,class
,define
等)编写程序,在Lisp中将代码写为(嵌套)列表(顺便说一句,这允许直接表达abstract syntactic trees)。再一次:你编写的程序看起来就像语言的数据结构。
当您将其作为数据进行讨论时,您将其称为“list”,但当您谈论程序代码时,您应该更好使用术语“s-expression”。因此,从技术上讲它们是相似的,但在不同的环境中使用。这些术语混合的唯一真正的地方是元编程(通常使用宏)。
另请注意,s-expression也可能只包含 atom (如数字,字符串等)。
答案 3 :(得分:4)
S表达式的简单定义是
(define S-expression?
(λ (object)
(or (atom? object) (list? object))))
;; Where atom? is:
(define atom?
(λ (object)
(and (not (pair? object)) (not (null? object)))))
;; And list? is:
(define list? (λ (object)
(let loop ((l1 object) (l2 object))
(if (pair? l1)
(let ((l1 (cdr l1)))
(cond ((eq? l1 l2) #f)
((pair? l1) (loop (cdr l1) (cdr l2)))
(else (null? l1))))
(null? l1)))))
答案 4 :(得分:0)
两者都是用类似的方式写的:(等等等等),可能是嵌套的。有一点不同 - 列表以撇号为前缀。
评估:
如果需要,我们可以将列表转换为s-exp,反之亦然。
<强> IAS:强>