私はコードを持っています
(define alternate
(letrec ([f (lambda (x) (cons x (lambda () (f (+ x 1)))))])
(lambda () (f 1))))
結果は1,2,3.です。1,2,1,2,1,2。を取るように変更するにはどうすればよいですか。
私はfの中で短所を試しましたが、うまくいきませんでした。何か案は?
私はコードを持っています
(define alternate
(letrec ([f (lambda (x) (cons x (lambda () (f (+ x 1)))))])
(lambda () (f 1))))
結果は1,2,3.です。1,2,1,2,1,2。を取るように変更するにはどうすればよいですか。
私はfの中で短所を試しましたが、うまくいきませんでした。何か案は?
これは、ストリームを使用して実装するのは簡単です。
(define (alternate)
(stream-map (lambda (x)
(if (even? x) 1 2))
(in-naturals)))
ここでの秘訣は、stream-consを使用してストリームを構築することです。これは、基本的に手動で実装していることを実行します。つまり、必要な場合にのみ評価される要素が「promises」であるリストを作成します。
stream-cons
レイジーストリームを生成します。stream-firstはfirst-exprの評価を強制してストリームの最初の要素を生成し、stream-restはrest-exprの評価を強制して残りの返されるストリームのストリームを生成します。
これはalternate
、フォームの要素の無限のストリームを返す方法を示しています1 2 1 2 1 2 ...
(define alt (alternate))
(stream-ref alt 0)
=> 1
(stream-ref alt 1)
=> 2
(stream-ref alt 2)
=> 1
(stream-ref alt 3)
=> 2
または、シーケンスのn個の要素のリストが必要な場合は、この手順を使用します。ちなみに、これはそもそもラケットの一部である必要があります。
(define (stream-take s n)
(if (zero? n)
'()
(cons (stream-first s)
(stream-take (stream-rest s) (sub1 n)))))
これで、期待どおりに機能します。
(define alt (alternate))
(stream-take alt 0)
=> '()
(stream-take alt 1)
=> '(1)
(stream-take alt 2)
=> '(1 2)
(stream-take alt 3)
=> '(1 2 1)
ジェネレーターも役立つかもしれません:docs
Welcome to DrRacket, version 5.3.3.5 [3m].
Language: racket [custom].
> (require racket/generator)
> (define g (generator () (let LOOP () (yield 1) (yield 2) (LOOP))))
> (g)
1
> (g)
2
> (g)
1
> (g)
2
アップデート:
さらに良いことに、無限ジェネレータを使用します。
Welcome to DrRacket, version 5.3.3.5 [3m].
Language: racket [custom].
> (require racket/generator)
> (define g (infinite-generator (yield 1) (yield 2)))
> (g)
1
> (g)
2
> (g)
1
> (g)
2
これを既存のコードの小さな変更として行う方法は次のとおりです。
(define alternate
(letrec ([f (lambda (x) (cons x (lambda () (f (if (= x 1) 2 1)))))])
(lambda () (f 1))))