我有代码
(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 中尝试了 cons 但没有用。有任何想法吗?
我有代码
(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 中尝试了 cons 但没有用。有任何想法吗?
使用流很容易实现:
(define (alternate)
(stream-map (lambda (x)
(if (even? x) 1 2))
(in-naturals)))
这里的技巧是流是使用stream-cons构建的,它基本上可以完成您手动实现的操作:它创建一个列表,其中的元素是“承诺”,仅在需要时才被评估。
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 个元素的列表,请使用此过程,顺便说一下,它首先应该是 Racket 的一部分:
(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))))