计划内的程序内的计数器

时间:2013-12-04 23:07:13

标签: scheme counter

我编写了一个程序,在调用时显示消息“msg0”“freq0”次和“msg1”“freq1”次,并且会定期执行此操作。

这是我的代码:

(define (make-counter n)
  (lambda () (set! n (+ n 1)) n))

(define counter1 (make-counter -1))

(define (rotating-msg msg0 msg1 freq0 freq1)
  (let ([period (+ freq0 freq1)]
        [count (counter1)])
    (cond ((< (remainder count period) freq0) msg0)
          (else msg1))))

只要我按照以下方式调用它,这就像我预期的那样:

> (rotating-msg 'foo 'bar 1 2)
foo
> (rotating-msg 'foo 'bar 1 2)
bar
> (rotating-msg 'foo 'bar 1 2)
bar
> (rotating-msg 'foo 'bar 1 2)
foo

但是,以下情况不起作用:

> (define foobar (rotating-msg 'foo 'bar 1 2))
> foobar
foo
> foobar
foo
> foobar
foo

这个与前一个完全不同的是什么?

1 个答案:

答案 0 :(得分:0)

在您的第一个示例中,您每次都会调用counter1,这会将n加1。在第二个示例中,counter1仅被调用一次,因此n保持在值0。

这种规范方式如下:

(define (rotating-message msg0 msg1 freq0 freq1)
  (let ((n 0) (total (+ freq0 freq1)))
    (lambda ()
      (let ((nn (modulo n total)))
        (begin0
          (if (< nn freq0) msg0 msg1)
          (set! n (+ n 1)))))))

(define r (rotating-message 'foo 'bar 1 2))

(for/list ((i (in-range 10))) (r))
=>'(foo bar bar foo bar bar foo bar bar foo)