Я согласен с другим ответом, что проблема с кодом OP состоит в том, что random-stream
является потоком, для которого (stream-first random-stream)
является некоторым случайным числом, в то время как (stream-rest random-stream)
также является тем же потоком, начинающимся с того же номера.
Я не совсем согласен с « функция без аргументов является правильным решением », хотя.
Одним из альтернативных решений было бы использование stream-map
для отображения случайного числа над натуральными числами:
(define random-stream/1-10
(stream-map (lambda (x) (random 1 11)) (in-naturals)))
Было бы даже лучше создать функцию, которая создает поток случайных чисел:
(define (random-stream a b)
(stream-map (lambda (x) (random a b)) (in-naturals)))
Эта функция может использоваться для создания потока (обратите внимание, что in-naturals
также является функцией, которая создает потоки):
random_streams.rkt> (define my-stream (random-stream 1 11))
random_streams.rkt> (stream->list (stream-take my-stream 10))
'(1 1 2 7 5 7 4 2 2 9)
Используя эту идею функции, которая создает потоков, stream-cons
метод может быть спасен:
(define (random-stream-cons a b)
(stream-cons (random a b) (random-stream-cons a b)))
Когда stream-first
вызывается в потоке, созданном с random-stream-cons
, возвращается случайное число; когда stream-rest
вызывается в том же потоке, возвращается другой поток со случайным числом в качестве первого элемента.
Созданные потоки являются постоянными:
random_streams.rkt> (stream->list (stream-take random-stream/1-10 10))
'(10 9 9 1 2 7 6 2 6 6)
random_streams.rkt> (stream->list (stream-take random-stream/1-10 15))
'(10 9 9 1 2 7 6 2 6 6 10 1 2 8 5)
random_streams.rkt> (define my-stream-1 (random-stream 1 11))
random_streams.rkt> (stream->list (stream-take my-stream-1 10))
'(1 4 1 10 7 9 9 9 2 9)
random_streams.rkt> (stream->list (stream-take my-stream-1 15))
'(1 4 1 10 7 9 9 9 2 9 2 3 9 9 10)
random_streams.rkt> (define my-stream-2 (random-stream-cons 1 11))
random_streams.rkt> (stream->list (stream-take my-stream-2 10))
'(10 4 6 1 4 2 10 5 3 6)
random_streams.rkt> (stream->list (stream-take my-stream-2 15))
'(10 4 6 1 4 2 10 5 3 6 1 5 7 5 5)
Эта random-stream-cons/1-10
функция по сути такая же, как и у предыдущей функции random-stream-cons
(но без аргументов); но ни один из них не является потоками . Обе они являются функциями, которые создают потоков:
(define (random-stream-cons/1-10) (stream-cons (random 1 11) (random-stream-cons/1-10)))
Каждый раз, когда вызывается одна из этих функций создания потока, возвращается новый поток:
random_streams.rkt> (stream->list (stream-take (random-stream-cons/1-10) 10))
'(10 8 3 10 8 8 1 8 4 5)
random_streams.rkt> (stream->list (stream-take (random-stream-cons/1-10) 10))
'(1 8 7 3 8 2 2 10 6 5)
Это может быть только то, что желательно; такие функции очень полезны, например, в контексте итерации:
random_streams.rkt> (for ([x (stream-take (random-stream 1 11) 5)])
(displayln x))
2
8
9
1
3
Итак, функции, которые возвращают потоки, полезны, и результирующие потоки могут быть связаны с символом, если это необходимо. Для потоков, которые могут понадобиться несколько раз с разными значениями, аргументы могут быть предоставлены в пользовательских функциях создания потока. Но для одноразовых потоков stream-map
уже выполняет работу по возврату потока, который может быть привязан к символу так же, как первоначально писал OP.