I wrote a procedure that displays a message "msg0" "freq0" times and "msg1" "freq1" times as it is called and keeps doing this periodically.
Here is my code for such a procedure:
(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))))
This works as I intended as long as I call it the following way:
> (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
However, the following does not work:
> (define foobar (rotating-msg 'foo 'bar 1 2))
> foobar
foo
> foobar
foo
> foobar
foo
In what way exactly is this one different from the previous one?
In your first example, you call counter1
every time, and this adds 1 to n. In your second example, counter1
is only called once and hence n stays at value 0.
The canonical way for this is as follows:
(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)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.