我知道您可以使用'
(又名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)
为什么呢?我认为'
只是一种方便的简写,为什么行为不同?
答案 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?”