为什么在函数定义中合法进行自我调用但对于值是非法的?

Rah*_*ahn 3 scheme functional-programming sicp racket

计算机程序的结构和解释(SICP)3.5.2引入了无限流:

(define ones
  (cons-stream 1 ones))
Run Code Online (Sandbox Code Playgroud)

此代码在DrRacket中不起作用,错误如下:

一个:未定义; 在定义之前不能引用标识符

其他代码如下:

(define (integers-starting-from n)
  (cons-stream n
               (integers-starting-from (+ n 1))))

(define integers (integers-starting-from 1))
Run Code Online (Sandbox Code Playgroud)

产生错误:

交互禁用

(陷入无限循环?)

据我所知(SICP),实现无限流的关键是延迟评估:

(define (delay exp)
  (lambda () exp))

(define (cons-stream a b)
  (cons a
        (delay b)))
Run Code Online (Sandbox Code Playgroud)

有了这个cons-stream,无限流仍然是非法的.

这样的数据结构让我想起了递归函数,在其定义中,自调用是合法的(在编译中)是否在实际退出之内.

为什么值引用自身是非法的?连参考都被推迟了?

其他编程语言可以支持无限流吗?

如果没有,它是关于处理器处理汇编语言的方式吗?数据堆栈的东西?

Syl*_*ter 5

在创建过程时,在启动过程主体时已经评估了参数.因此delay它不会做任何事情,因为它已经在那时计算过了.cons-stream需要成为一个宏.

DrRacket不是一种语言实现.它是一个支持许多语言的IDE.其中之一是SICP兼容性语言.我使用DrRacket中的代码管理您的代码而不会出错:

#!planet neil/sicp

(define ones
  (cons-stream 1 ones))

(define (integers-starting-from n)
  (cons-stream n
               (integers-starting-from (+ n 1))))

(define integers (integers-starting-from 1))
Run Code Online (Sandbox Code Playgroud)

它就像一个魅力.在DrRacket的默认语言,#!racket,有溪流过,但名称不同:

#!racket 

(define ones
  (stream-cons 1 ones))

(define (integers-starting-from n)
  (stream-cons n
               (integers-starting-from (+ n 1))))

(define integers (integers-starting-from 1))
Run Code Online (Sandbox Code Playgroud)

但是对于Scheme,您应该使用SRFI-41,您可以同时使用#!racket(使用(require srfi/41))和#!r6rs(和R7RS-large完成时)

(import (rnrs)
        (srfi :41))

(define ones
  (stream-cons 1 ones))

(define (integers-starting-from n)
  (stream-cons n
               (integers-starting-from (+ n 1))))

(define integers (integers-starting-from 1))
Run Code Online (Sandbox Code Playgroud)

要在两者中滚动您自己的SICP流#!racket,#!r6rs您可以使用define-syntax

(define-syntax stream-cons 
  (syntax-rules ()
    ((_ a d) (cons a (delay d)))))
Run Code Online (Sandbox Code Playgroud)

请注意,RSFI-41和球拍拥有流库,用于#!racket延迟a中的两个值,stream-cons而不仅仅是SICP版本中的尾部.