Lisp:list vs S-expression

时间:2012-05-27 01:54:07

标签: list lisp s-expression

我正在研究Lisp。我遇到了两个术语“列表”和“S表达式”。我只是无法区分它们。它们只是Lisp中的同义词吗?

5 个答案:

答案 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表达式,它表示一个由原子+12组成的平面列表。

但是,在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 符号表达式的缩写)被描述为:

  • 符号,例如FOOBAR
  • cons cells ,其中s表达式作为其第一个和第二个元素:( 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|
  • 数字:1231.01/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)不同,您使用特殊语法({}classdefine等)编写程序,在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-expression返回一些结果(可能是原子或列表或零或其他)
  • 列出返回列表

如果需要,我们可以将列表转换为s-exp,反之亦然。

  • (eval'(blah blah blah))=&gt; list被视为s-exp,并返回结果。
  • (引用(blah blah blah))=&gt; sexp将转换为列表,并返回列表而不进行评估

<强> IAS:

  • 如果将List视为数据,则将其称为List,如果将其视为代码,则将其称为s-exp。