引号和列表有什么区别?

时间:2016-01-25 03:18:36

标签: scheme racket evaluation quote

我知道您可以使用'(又名quote)来创建列表,我会一直使用它,如下所示:

> (car '(1 2 3))
1

但它并不总是像我期望的那样起作用。例如,我试图创建一个像这样的函数列表,但它不起作用:

> (define math-fns '(+ - * /))
> (map (lambda (fn) (fn 1)) math-fns)
application: not a procedure;
  expected a procedure that can be applied to arguments
  given: '+

当我使用list时,它有效:

> (define math-fns (list + - * /))
> (map (lambda (fn) (fn 1)) math-fns)
'(1 -1 1 1)

为什么呢?我认为'只是一种方便的简写,为什么行为不同?

1 个答案:

答案 0 :(得分:0)

您看到的行为是Scheme未将符号视为函数的结果。

表达式'(+ - * /)产生一个值,该值是符号列表。仅仅是因为(+ - * /) 是符号列表,而我们只是引用它来抑制求值,以便从字面上获取该对象作为值。

表达式(list + - * /)产生函数列表。这是因为它是一个函数调用。计算符号表达式list+-*/。它们都是表示功能的变量,因此简化为那些功能。然后调用list函数,并返回其余四个函数的列表。

在ANSI Common Lisp中,将符号作为函数调用是有效的:

[1]> (mapcar (lambda (f) (funcall f 1)) '(+ - * /))
(1 -1 1 1)

在需要功能的地方使用符号时,将替换符号的顶级功能绑定(如果有的话),并且一切都很棒。

如果要使用list来生成符号列表,就像'(+ - * /)一样,则必须单独引用它们以抑制它们的求值:

(list '+ '- '* '/)

您将看到,如果您对此map进行操作,它将以相同的方式失败。

显示的错误消息具有误导性:

expected a procedure that can be applied to arguments
given: '+

根本没有给涂药者(quote +),而是给了+。这里发生的是,符号+正在以“打印为表达式”模式打印,这是Racket的功能,我想您正在使用它。

在“作为表达式打印”模式下,必须使用并对其进行评估的语法来打印对象,以生成类似的对象。请参阅StackOverflow问题“ Why does the Racket interpreter write lists with an apostroph before?