【问题标题】:Meaning of 'quote in LispLisp中'引号的含义
【发布时间】:2013-12-17 19:37:04
【问题描述】:

这个问题是在阅读SICP时出现的。为什么(list 'quote '(a b c)) 被解释器(R5RS in Dr.Racket)评估为'(a b c)。对我来说应该是(quote (a b c))。例如(list 'quot '(a b c)) 被评估为(quot (a b c))'quote有什么特别之处?

【问题讨论】:

  • 你用的是什么解释器?
  • 由于其他答案本质上是重复的,我将在此处添加此内容,以补充他们所说的内容:即使您正在查看单引号语法,您真正看到的是非-empty list(consp ''42) 为真(返回非nil)。

标签: scheme lisp sicp


【解决方案1】:

您将获得不同的行为,具体取决于您正在使用的 Lisp(Scheme、Racket、Common Lisp 等),但一般情况下,系统将接受 'x 作为简写语法糖 表示 (quote x)。这两种形式完全相同,它们的值也相同:未计算的x。当系统输出结果时,它可能会选择以第一种方式打印以使结果对用户更直观。 cons 也发生了类似的事情。例如,

(cons 1 2)
;=> (1 . 2)

因为这是打印 cons 单元格(对)的一般方式。但是,当对的第二部分是另一个列表(空列表() 或另一个对,这就是我们有以下内容的原因时,定义了一个特殊情况。我还写了更多关于如何列表和cons 单元格打印在Recursive range in Lisp adds a period? 的答案中。

(cons 1 '())
;=> (1)

(cons 1 '(2 3))
;=> (1 2 3)

现在,我已经编写了上面表达式的。例如,(cons 1 '(2 3)) 形式的 是列表 (1 2 3)。作为一个额外的复杂因素,某些系统(我认为某些语言尤其是 Dr. Racket)不会在交互式提示中打印表单的 ,而是打印一个表单将产生相同的(对于“相同”的某些解释)值。例如,您可能会评估 '(1 . 2) 并查看输出 (cons 1 2),因为这是另一个会产生相同值的 form。如果您正在执行具有referential transparency函数式编程,这可能会有所帮助,但如果您不期望它,它可能会导致一些混乱。

无论系统如何打印它们,查看我们正在获得我们应该得到的结果的一个好方法是检查它们。我们期望(list 'quote '(a b c)) 应该返回一个列表,其car 是符号quote,其cadr 是列表(a b c)。这就是我们得到的(在 Racket 5.3 博士中,语言为 R5RS):

> (display (list 'quote '(a b c)))
'(a b c)
> (display (car (list 'quote '(a b c))))
quote
> (display (cadr (list 'quote '(a b c))))
(a b c)

如果我们使用'qmmmt 而不是'quote,我们会得到类似的结果:

> (display (list 'qmmmt '(a b c)))
(qmmmt (a b c))
> (display (car (list 'qmmmt '(a b c))))
qmmmt
> (display (cadr (list 'qmmmt '(a b c))))
(a b c)

唯一的区别是,在第一种情况下,display 使用可用于此类列表的简写显示其 car 是符号 quote 的列表。也就是说,不是显示(quote (a b c)),而是显示'(a b c)

【讨论】:

    【解决方案2】:

    '(a b c)(quote (a b c)) 实际上是相同的不同符号。因此,如果您的 Lisp 打印出较短的版本,请不要感到惊讶。

    一般'<something>(quote <something>)相同。

    QUOTE 在 Lisp 中用于标记应该对自己求值的表达式。通常列表是函数或宏调用,符号是变量。如果您想将它们视为数据,则需要引用它们。

    由于 (quote <something>) 在 Lisp 中经常使用,因此引入了缩写版本 '<something> 以节省一些打字或阅读时间...

    【讨论】:

    • 我想强调在问题中我使用的是'quote 而不是quote'quote 的表示方式也不同,例如,不像 'qmmmt
    • 例如(list 'quote '(a b c))表示为'(a b c)(list 'c 'quote '(a b c))表示为(c quote (a b c))(list 'quo '(a b c))表示为(quo (a b c))
    • @Graduate 系统可以分别打印列表(quote abc) 和列表(qmmmt abc)(如'abc(qmmmt abc)),但两者都是列表;如果您对它们调用firstsecond,您将看到预期值。这只是打印的问题。
    • 我只是对为什么它的打印不同感兴趣。
    【解决方案3】:

    display 发出一些行为。例如。 '(a . (b . (c . ()))) 显示为(a b c)'quote 显示为quote 并且可能'(quote x y) 显示为(quote x y)'(quote x) 显示为'x(quote x)。哪一个取决于实现,但两者含义相同。

    作为数据(即引用,如(quote quote) 和它的缩写'quote)评估的结果,符号quote 没有什么特别的,对于任何LISP,就像'+'potato 发生成为符号+potato。任何在不被引用时表示某事的符号在被引用时都没有特殊意义。

    【讨论】:

    • 明确您是在代码块中放置values 还是forms 非常重要。当您说(quote quote) 缩写为'quote 时,您说的是长度为2 的列表的值,其每个元素都是符号quote。但是,当您说 '+'potato 是符号时,您的意思是 forms '+'potato 在评估时会产生符号 + 和符号potato。通常,从上下文中可以清楚地看到含义,但这是一个关于事物在不同上下文中的含义的问题。
    • @JoshuaTaylor 和(quote quote) 我在想一种形式……例如。 quote 被绑定到一个特殊的形式,并且它的应用程序将形式变成了(非特殊)符号quote,就像 '+ 转变成一个非特殊符号,因为它在评估 + 时被引用是完全不同的。对于像我这样的算法程序员来说,找到一个类比并不是一件容易的事,所以需要一些时间来适应:)
    【解决方案4】:

    我也花了一段时间才理解这个问题。但这只是您善良的 lisp 解释器以等效形式 '(a b c) 显示 (quote (a b c))。由于 (quott (a b c)) 没有这样的等价/语法糖,因此按原样显示。

    【讨论】:

    • 我想我开始明白了。如果 A = (quote (a b c)),B = '(a b c),并且 A 等于 到 B,它们的表示方式相同。所以(quote A) 必须等于(quote B) 并以相同的方式表示。
    • @Graduate (quote A) 不等于 (quote B),因为 quote 没有评估参数。您最终会得到符号 A 和符号 B,它们稍后可能会被评估为相同的东西,但 quote 不会评估。
    • 您可能还想检查标准泛型方法 print-object。如果您 defmethod print-object 为您自己的课程,Lisp 打印机(将 (quote) 打印为 ' 的同一台打印机)将在任何地方以您想要的方式打印您的对象。我刚刚尝试为符号'quote 重载打印对象,有趣的是,它并没有改变 sbcl 的任何内容,而是在 LispWorks 工作。我不知道这是标准未定义的行为,甚至为 sbcl 提交了一个错误,幸运的是很快就被拒绝了:/
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多