scheme simple stream-map 在 SICP 示例中不起作用

标签 scheme lisp sicp delayed-execution

摘自 SICP 书, 对于给出的最后一行,方案代码编译存在问题, 在我看来,函数 sqr 和 shower 都是返回单个值的单个参数的函数。因此应该工作。 对于方案中的以下给定代码:

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

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

;; cons-stream needs to be a macro

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

(define the-empty-stream '())

(define stream-null? null?)

;; define stream-for-each
;; run a procedure on each element of stream
(define (stream-for-each proc stream)
  (if (stream-null? stream)
      'done
      (begin (proc (stream-car stream))
             (stream-for-each proc (stream-cdr stream)))))

(define test-stream (cons-stream 2 (cons-stream 3 (cons-stream 4 '()))))

;; displays passed argument but with a newline
(define (display-line x)
  (newline)
  (display x))

(define (display-stream stream)
  (stream-for-each display-line stream))

;; stream map
(define (stream-map proc stream)
  (if (stream-null? stream)
      the-empty-stream
      (cons-stream (proc (stream-car stream))
                   (stream-map proc (stream-cdr stream)))))

(define (sqr x)
  (* x x))

(define (stream-enumerate-interval low hi)
  (if (> low hi)
      '()
      (cons-stream low (stream-enumerate-interval (+ 1 low) hi))))

(define (shower x)
  (display-line x)
  x)

;; this works
(define yyy (stream-map sqr (stream-enumerate-interval 1 10)))


;; reason why below wont work?
;; (define xxx (stream-map shower (stream-enumerate-interval 1 10)))

另外,根据 SICP 书,它定义了一个不同版本的流映射,它允许接受可以采用多个参数的过程的过程。

我不明白需要不同的流图以及为什么最后一行上面的流图代码不起作用

最佳答案

它们都可以工作,但由于 stream-map 是惰性的,除非您强制执行某些操作,否则您不会对它们进行完整计算。例如。让stream->list:

(define (stream->list stream)
  (if (stream-null? stream)
      '()
      (cons (stream-car stream)
            (stream->list (stream-cdr stream)))))

(stream->list yyy)
; ==> (1 4 9 16 25 36 49 64 81 100)

(stream->list zzz)
; ==> (1 2 3 4 5 6 7 8 9 10) (and as a side effect prints then one line at a time)

事实是,除非您尝试访问该值,否则列表其余部分的实际计算永远不会完成。 stream->list 强制计算整个流,然后计算它。

请注意,无论如何,sicp 流总是强制使用第一个值。这是其他流库已在 SRFI-41 中修复的简化。除非您访问结果,否则您不会有任何副作用。

#!r6rs
(import (rnrs)
        (srfi :41))

;; nothing is displayed after this expression is evaluated 
(define squares (stream-map (lambda (x) (shower (* x x)))
                            (stream-from 0)))

(stream-car squares)
; ==> 0 (displays "\n0")

(stream->list 4 squares)
; ==> (0 1 4 9) 
; (displayes "\n1\n4\n9" since "0" is already calculated.) 

关于scheme simple stream-map 在 SICP 示例中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43682333/

相关文章:

scheme - `if` 语句在 Scheme 中是如何工作的?

scheme - 为什么 "eq?"在以下上下文中评估为 false 而在其他情况下评估为 true?

recursion - 读取深度嵌套的树会导致堆栈溢出

支持套车方案!并设置-CDR!在sicp中

algorithm - 手动计算递归斐波那契算法的时间复杂度

lisp - SICP car/cdr练习题问题

lisp - 在 Notepad++ 中编译 lisp/scheme

scheme - 在 lisp 中反转带有子列表和原子的列表

Lisp - if 语句各种 Action

scheme - (define (add x y) (+ x y)) 和 (define add (lambda (x y) (+ x y))) 有什么区别?