lambda 表达式中的球拍和未绑定标识符,与 r5rs 对比
Racket and unbound identifier in lambda expression, contrast with r5rs
在 DrRacket 中,当我将语言设置为 R5RS 并且 运行 以下代码时:
(lambda (x) z)
它 运行 没有错误并且 returns #<procedure>
。这对我来说很有意义; lambda 形式定义了一个过程,其主体尚未被评估,因此返回该过程。
或者,当我使用 Racket 语言方言时,出现以下错误:
z: unbound identifier in module in: z
我不明白为什么 Racket 会产生这个错误。我的意思是,当然我看到 z
是未定义的,但我对评估模型的理解是函数体在函数定义时不被评估。这与 R5RS 结果一致,但与 Racket 结果不一致。 Racket 到底在做什么?是不是在代码体中以某种方式 "peeking" 来查看变量是否被定义?导致这种不同行为的 R5RS 评估模型有何不同?
Racket 中的源文件
#lang racket
(define f (lambda (x) z))
结果:
z: unbound identifier in module in: z
REPL 交互:
Welcome to DrRacket, version 6.1.1 [3m].
Language: racket; memory limit: 128 MB.
> (define f (lambda (x) z))
>
没有错误。
定义了 z 的源文件:
#lang racket
(define f (lambda (x) z))
(define z 5)
没有错误。
因此,Racket 确保源文件中的所有变量都已定义,而不对 REPL 代码做出相同的保证。我只能认为这是一件好事,因为它可以防止源文件中出现错误。
一个#lang
文件是模块。文档中详细描述了如何扩展和评估模块的规范。经过一番挖掘,我发现了这条注释:
No identifier can be imported or defined more than once at any phase
level within a single module. Every exported identifier must be
imported or defined. No expression can refer to a top-level variable.
最后一句"No expression can refer to a top-level variable."表示必须绑定所有变量
相反,在repl中输入的表达式不是模块,而是"outside"任何模块的表达式。对未绑定变量的引用成为对顶级变量的引用。计算表达式时,将在当前命名空间中查找顶级变量的值。如果在查找时,变量没有关联值,则会发出错误信号。
repl 使用这个复杂的规则是为了允许定义相互递归函数,一次定义一个。
有关 REPL 的更多信息,请参阅:
https://gist.github.com/samth/3083053
在 DrRacket 中,当我将语言设置为 R5RS 并且 运行 以下代码时:
(lambda (x) z)
它 运行 没有错误并且 returns #<procedure>
。这对我来说很有意义; lambda 形式定义了一个过程,其主体尚未被评估,因此返回该过程。
或者,当我使用 Racket 语言方言时,出现以下错误:
z: unbound identifier in module in: z
我不明白为什么 Racket 会产生这个错误。我的意思是,当然我看到 z
是未定义的,但我对评估模型的理解是函数体在函数定义时不被评估。这与 R5RS 结果一致,但与 Racket 结果不一致。 Racket 到底在做什么?是不是在代码体中以某种方式 "peeking" 来查看变量是否被定义?导致这种不同行为的 R5RS 评估模型有何不同?
Racket 中的源文件
#lang racket
(define f (lambda (x) z))
结果:
z: unbound identifier in module in: z
REPL 交互:
Welcome to DrRacket, version 6.1.1 [3m].
Language: racket; memory limit: 128 MB.
> (define f (lambda (x) z))
>
没有错误。
定义了 z 的源文件:
#lang racket
(define f (lambda (x) z))
(define z 5)
没有错误。
因此,Racket 确保源文件中的所有变量都已定义,而不对 REPL 代码做出相同的保证。我只能认为这是一件好事,因为它可以防止源文件中出现错误。
一个#lang
文件是模块。文档中详细描述了如何扩展和评估模块的规范。经过一番挖掘,我发现了这条注释:
No identifier can be imported or defined more than once at any phase level within a single module. Every exported identifier must be imported or defined. No expression can refer to a top-level variable.
最后一句"No expression can refer to a top-level variable."表示必须绑定所有变量
相反,在repl中输入的表达式不是模块,而是"outside"任何模块的表达式。对未绑定变量的引用成为对顶级变量的引用。计算表达式时,将在当前命名空间中查找顶级变量的值。如果在查找时,变量没有关联值,则会发出错误信号。
repl 使用这个复杂的规则是为了允许定义相互递归函数,一次定义一个。
有关 REPL 的更多信息,请参阅: https://gist.github.com/samth/3083053