在一个 func 定义中使用该特殊形式后重新定义该特殊形式不会影响 Scheme 中的该定义

问题描述 投票:0回答:1

我正在阅读 SICP 第 3.5.1 节,其中给出了 MIT/GNU 方案中提供的原始程序的实现。

我尝试加载这些实现而不考虑顺序,因为它们都是

(define ...)
,但实际上顺序很重要(对于以下简化的演示,我们需要在
(define (cons-stream a b) ...)
之前运行
(define (stream-enumerate-interval low high) ...)
)。

我跑步:

;; case 1
(define (stream-enumerate-interval low high)
  (if (> low high)
      the-empty-stream
      (cons-stream
       low
       (stream-enumerate-interval (+ low 1) high))))

(stream-enumerate-interval 0 10)

(define (cons-stream a b)
  (display "call cons-stream")
  (cons a (delay b)))

(stream-enumerate-interval 0 10)
; not output "call cons-stream"

;; case 2
(define (cons-stream-1 a b)
  (display "call cons-stream")
  (cons a (delay b)))

(define (stream-enumerate-interval low high)
  (if (> low high)
      the-empty-stream
      (cons-stream-1
       low
       (stream-enumerate-interval (+ low 1) high))))

(stream-enumerate-interval 0 10)

(define (cons-stream-1 a b)
  (display "call cons-stream-1")
  (cons a (delay b)))

(stream-enumerate-interval 0 10)
; will use the new "cons-stream-1" by outputing "call cons-stream-1".

;; case 3
(define (test-redefine-+ . args)
  (display (apply + args)))

(test-redefine-+ 2 3 4)
(define (+ . args)
  (apply * args))
(test-redefine-+ 2 3 4)
; redefinition works by outputing 24.

正如所说:

我们假设有一个全局环境,由单个框架(没有封闭环境)组成,其中包括与原始过程相关的符号的

通过构造一个框架,将过程的形式参数绑定到调用的参数,然后在构造的新环境的上下文中评估过程的主体,将过程对象应用于一组参数。新框架将应用过程对象的环境部分作为其封闭环境。

通过计算相对于给定环境的 lambda 表达式来创建过程。生成的过程对象是由

lambda 表达式的文本和指向创建过程的环境的指针组成的对。

正如上面所说,我们只记录

define时的“lambda表达式的text

”,而不像
cons-stream
那样记录里面使用的procedure的值。

所以恕我直言,当我们调用第二个

(stream-enumerate-interval 0 10)

时,我们将尝试通过参数绑定在“新环境”中查找
cons-stream
的值。既然这会失败,那么我们看看“封闭环境”,即这里的全局环境。然后
预计cons-stream
已绑定到新值
。但事实并非如此。

但是,对于用户自定义的

lambda

 func 
cons-stream-1
 则不会出现上述问题。有人可以告诉我这两种情况对应的环境图之间的区别吗(不需要画图,可能很常规且乏味。清晰的文字对我来说就可以了)?

scope scheme evaluation sicp mit-scheme
1个回答
0
投票
这与环境无关:它与必须如何定义

cons-stream

 有关。  你的两个定义都是不正确的,因为 
cons-stream
 必须定义为

(cons-stream a b)

 相当于 
(cons a (delay b))
(从 3.5.1 开始)。

这样的东西不能被定义为应用顺序语言中的过程,因为像

(a b c)

 这样的形式被评估为:

    按某种顺序评估
  1. a
    b
    c
  2. a
     的评估结果应用于评估两个参数的结果。

cons-stream

delay
都不能以这种方式实现,因为它们不得评估一个或多个论点。

相反,它们要么是由语言定义的原语,要么是

,可以将其视为指定源的某些位如何转换为源的其他位的规则。

这意味着,例如,

(define upfrom (lambda (v) (cons-stream v (upfrom (+ v 1))))) (define upfrom-0 (upfrom 0))
会起作用:很容易看出它不能这样做 - 它将无法终止 - 根据您对 

cons-stream

 的定义。

然后发生的事情是,在您将

cons-stream

 定义为普通过程之前,源代码到其他源代码的转换已经发生。

© www.soinside.com 2019 - 2024. All rights reserved.