方案中的流-通过方案中的流图定义整数

nan*_*han 5 scheme stream sicp lazy-sequences racket

如何在Scheme中通过流映射定义整数:

(定义整数(stream-cons 1(stream-map * something * * something *)))

use*_*810 5

(define integers
  (stream-cons 1
    (stream-map add1 integers)))
Run Code Online (Sandbox Code Playgroud)

有关流的更多信息,请参阅SRFI-41 。


Ósc*_*pez 5

@user448810 的答案是完美的,它将在 Racket 中工作(它使用 Racket 特定的程序)。但这个问题也被标记为SICP,所以这是我的两分钱。

仅使用 SICP 中可用的 Scheme 过程的子集来回答问题会产生等效但略有不同的解决方案,仅使用书中定义的以下原始流操作:stream-null? stream-cons stream-car stream-cdr。特别要注意的是,这stream-map不是Scheme的标准部分,在书中它是根据原始操作来实现的,比Racket的实现有一个优势——它可以接收可变数量的流作为参数:

(define (stream-map proc . args)
  (if (stream-null? (car args))
      the-empty-stream
      (stream-cons (apply proc (map stream-car args))
                   (apply stream-map (cons proc (map stream-cdr args))))))

(define (add-streams s1 s2)
  (stream-map + s1 s2))
Run Code Online (Sandbox Code Playgroud)

有了上面的过程,就很容易定义integers

(define ones (stream-cons 1
                          ones))

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

实际上,stream-map上面的过程受到一个错误的影响,如果我们向它提供两个流,其中第二个比第一个短,这个错误就会变得明显,如下所示:

(define (stream-map proc . args)
  (if (stream-null? (car args))
      the-empty-stream
      (stream-cons (apply proc (map stream-car args))
                   (apply stream-map (cons proc (map stream-cdr args))))))

(define (add-streams s1 s2)
  (stream-map + s1 s2))
Run Code Online (Sandbox Code Playgroud)

建议的实现stream-map将采用 的 else 分支if,因为(stream-null? (car args))is(stream-null? (cons-stream 1 the-empty-stream))为 false,因此它将尝试评估,(map stream-car args)而后者又会尝试评估(stream-car the-empty-stream),从而导致运行时失败。

以下是该过程的可能修复stream-map

(define ones (stream-cons 1
                          ones))

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