Scheme 方案:内部定义顺序

Scheme 方案:内部定义顺序,scheme,Scheme,这是SICP手册ch4中的一个问题,下面是代码 (let ((a 1)) (define (f x) (define b (+ a x)) (define a 5) (+ a b)) (f 10)) 如果使用lambda表达式,则错误消息为“a:未定义;无法在初始化之前使用” ((lambda (a) (define (f x) (define a 5) (define b (+ a x)) (+ a b)) (f 10)) 1)

这是SICP手册ch4中的一个问题,下面是代码

(let ((a 1))
  (define (f x)
    (define b (+ a x))
    (define a 5)
    (+ a b))
  (f 10))
如果使用lambda表达式,则错误消息为“a:未定义;无法在初始化之前使用”

((lambda (a)
  (define (f x)
    (define a 5)
    (define b (+ a x))
    (+ a b))
  (f 10)) 1)
仍然不起作用,但是如果我把它写成过程定义,像这样

(define (f a)
  (define (g x)
    (define b (+ a x))
    (+ a b))
  (g 10))
(f 1)

它运行没有错误,但这两个基本上是一样的,对吗?为什么let和lambda表达式失败?谢谢。

因为它指的是内部的
a
,而不是
let
中的那一个:

(let ((a 1))
  (define (f x)
    (define b (+ a x))   ; `a` here refers to
    (define a 5)         ;    **this one**
    (+ a b))
  (f 10))
内部
define
s都放在一个共享范围内。这样我们就可以定义相互递归的函数

如果您切换两个
define
s的顺序,它将起作用(将
a
定义置于
b
定义之上),因为
a
将在
b
初始化中使用之前进行初始化,但仅当您使用
#lang racket

#lang sicp
中,以下作品:

(let ((a 1))
  (define (f x)
    (define a 5)
    (define b (lambda () (+ a x)))
    (+ a (b)))
  (f 10))

您好,正如您所说,我将a定义置于b定义之上,但它仍然显示相同的错误(我使用#lang sicp在DrRacket中编写此代码)刚刚检查了
#lang sicp
,它确实抛出了一个错误。我想这是遵循了lang r5rs在这方面的领导。嵌套定义在共享的
letrec
中有效,在R5R中,在初始化期间禁止引用letrec变量的值。好吧……一个愚蠢的问题,为什么在b定义中,解释器在let(A1)中找不到a?我真的很困惑,谢谢你帮助我,因为你定义它引用
a
,在内部范围中有一个
a
,与
b
定义的范围相同。把这段代码放到Dr Racket中,用鼠标悬停变量,它会画出漂亮的箭头来显示哪个变量引用了什么定义。所以内部定义是同时计算的,而不是按顺序计算的,对吗?