替换两个值

时间:2013-02-24 22:32:59

标签: stream scheme racket lazy-sequences

我有代码

(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里面尝试过但是没有工作。 有什么想法吗?

3 个答案:

答案 0 :(得分:1)

使用streams实现这一点很简单:

(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 元素列表,请使用此过程,顺便说一句,它应该是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)

答案 1 :(得分: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

答案 2 :(得分:0)

以下是对现有代码进行小修改的方法:

(define alternate
  (letrec ([f (lambda (x) (cons x (lambda () (f (if (= x 1) 2 1)))))])
    (lambda () (f 1))))
相关问题