scheme simple stream-map 在 SICP 示例中不起作用
scheme simple stream-map will not work in SICP example
SICP 书中的摘录,
对于给出的最后一行,方案代码编译存在问题,
在我看来,函数 sqr 和 shower 都是 return 单个值的单个参数的函数。因此应该工作。
对于方案中的以下给定代码:
(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.)
SICP 书中的摘录, 对于给出的最后一行,方案代码编译存在问题, 在我看来,函数 sqr 和 shower 都是 return 单个值的单个参数的函数。因此应该工作。 对于方案中的以下给定代码:
(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.)