将符号定义为其他东西时,scheme 中发生了什么?

What happened in scheme when defining a symbol to be something else?

我是 Scheme 语言的初学者。

最近发现数据类型symbol可以用引号显示,像这样:

> 'E
E
> (quote E)
E

但是,如果执行下面的代码,每一种引用都可能失败:

> (define 'E 123)
> 'E
E: undefined;
 cannot reference an identifier before its definition
> 'abc
abc: undefined;
 cannot reference an identifier before its definition

那么当代码 (define 'E 123) 被执行时发生了什么?

首先你要求 Scheme 计算 (define 'E 123)。让我们在它前面加一个引号,看看没有 ' shorthand 会是什么样子。你总是可以这样做:引用任何表达式来询问 Scheme,“你认为这个值是多少?”

 > '(define 'E 123)
=> (define (quote E) 123)

嗯,在 Scheme 中,(define (x ...) ...)(define x (lambda (...) ...)) 的 shorthand:它只是一个方便的 shorthand 来定义一个函数。所以在这种情况下 (define (quote E) 123)(define quote (lambda (E) 123)) 相同。因此,您要重新定义的符号是 quote,并且您将其定义为一个参数的函数,该参数始终为 returns 123.

接下来您要求评估 'E。让我们再次扩展它以查看 shorthand:

 > ''E
=> (quote E)

您现在调用您定义的 quote 函数,并将变量 E 作为参数传递给它。但是 E 以前没有定义过,所以失败了。如果你愿意,你可以先定义 E 为任何值,然后 'E 可能会 return 123。这取决于你使用的是什么 Scheme 评估器:我找到的那个当您尝试重新定义 quote 时并不太感激它,但显然您并不介意,所以我怀疑您会得到 123,并且如果您定义 abc 然后求值,您会得到相同的结果'abc.

一般来说(define name ...)是在(bind name)作用域的开头进行转换,在define出现的地方执行(set! name ...)。您需要定义一个符号,而不是 (quote name)。因为define是一种特殊的形式,求值规则是特殊的,不是一般的应用——define不是函数调用。