You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Racket实现流时遭遇内存溢出问题求助

在Racket中实现SICP流结构时遭遇内存溢出

我业余时间在学《计算机程序的构造和解释》(也就是常说的“巫师书”),前面进展都很顺利,直到尝试实现第三章的流结构。我用的是(Dr)Racket而非标准Scheme,这可能是问题的根源。

核心问题是创建流时触发内存错误:interactions disabled; out of memory,我怀疑是delay的用法出了问题。

我先试了书中推荐的代码:

#lang racket

(define (cons-stream a b)
  (cons a (delay b)))

(define (car-stream s)
  (car s))

(define (cdr-stream s)
  (force (cdr s)))

这里直接调用了Racket自带的delay和force。后来我也按照书中的方式自行实现了delay和force,但还是遇到同样的内存错误。

为了测试功能,我写了两个用例:

  • 无限1流:
(define (ones) (cons-stream 1 (ones)))
  • 超大区间流:
(define (interval low high)
  (if (> low high)
      null
      (cons-stream low
                   (interval (+ low 1) high))))

(define (first-integers n)
  (interval 0 n))

(define test-interval
  (first-integers 10000000000000000000000000))

按我的理解,这两个测试用例都不该出问题,因为流应该是按需生成的,但实际却触发了内存问题,看起来代码在尝试生成整个流的内容。


问题原因与解决办法

Racket的delay和标准Scheme里的delay有个关键区别:Racket默认会对delay的参数进行严格求值(哪怕用了delay,参数在传入delay前就会被计算),而SICP里的delay是完全惰性求值,只会在force时才计算参数。你自己实现delay和force时,也没绕开Racket的严格求值规则,所以才会内存溢出。

贴合SICP的流实现

要在Racket里实现符合SICP预期的流,需要用lazy宏确保第二个参数不会被提前求值,修改后的代码如下:

#lang racket

(define-syntax cons-stream
  (syntax-rules ()
    [(cons-stream a b) (cons a (delay (lazy b)))]))

(define (car-stream s) (car s))
(define (cdr-stream s) (force (cdr s)))

更简单的方案:用Racket内置流库

直接用Racket自带的racket/stream模块,它已经实现了正确的惰性流逻辑,写法也和SICP的流思路一致:

#lang racket

(require racket/stream)

; 无限1流
(define ones (stream-cons 1 ones))

; 区间流实现
(define (interval low high)
  (if (> low high)
      empty-stream
      (stream-cons low (interval (+ low 1) high))))

(define test-interval (interval 0 10000000000000000000000000))

为什么你的代码会溢出

你写的(define (ones) (cons-stream 1 (ones))),在Racket的严格求值规则下,(ones)作为cons-stream的第二个参数,会被立即递归调用,哪怕套了delay也没用——因为delay的参数在传入前就被求值了,直接触发无限递归撑爆内存。用lazy包裹后,参数的求值会被完全推迟到force调用时,才会按需生成下一个流元素。

内容的提问来源于stack exchange,提问作者user11450692

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 05:32:40