我认为以下代码应定义1到10之间的随机数流:
(define random-stream (stream-cons (random 1 11) random-stream))
但是,它实际上的作用是定义特定随机数的流。例如:
> (stream->list (stream-take random-stream 10))
'(5 5 5 5 5 5 5 5 5 5)
我想这是(random 1 11)
首次解析定义时产生的随机数。我通过使random-stream
一个无参数的函数来解决这个问题:
(define (random-stream) (stream-cons (random 1 11) (random-stream)))
此作品:
> (stream->list (stream-take (random-stream) 10))
'(6 1 10 9 4 2 2 3 3 10)
因此,在我看来,可以理解,常量是在读取时求值的,而函数是在调用时求值的。通常这无关紧要,但是在流的情况下(您具有递归定义)会有所不同。
这是如何工作的,还是比这更微妙的?还有其他情况需要注意这一差异吗?
使random-stream
无参函数是正确的解决方案。
(define (random-stream) (stream-cons (random 1 11) (random-stream)))
我将解释原因。
通常使用(define my-stream (stream-cons ....))
定义流时,该流只有一个值。对my-stream
的任何引用都将产生相同的值。
(define my-stream (stream-cons (random 1 11) my-stream))
“ rest”内的my-stream
实际上是与eq?
相同的值my-stream
。
> (eq? my-stream (stream-rest my-stream))
#true
因此,因为它们是相同的值,所以可以在函数调用中将它们替换。如果(stream-first my-stream)
返回5,则(stream-first (stream-rest my-stream))
也必须返回5。
> (eq? (stream-first my-stream) (stream-first (stream-rest my-stream)))
#true
函数版本不是这种情况,因为每次调用该函数都会创建一个新的流值。
(define (random-stream) (stream-cons (random 1 11) (random-stream)))
> (eq? (random-stream) (random-stream))
#false
> (eq? (stream-first (random-stream)) (stream-first (random-stream)))
#false
由于“ rest”字段也称为(random-stream)
,所以其余部分与整体不同。
> (define generated-stream (random-stream))
> (eq? generated-stream (stream-rest generated-stream))
#false
> (eq? (stream-first generated-stream) (stream-first (stream-rest generated-stream)))
#false