方案中的动态价值

时间:2014-06-19 03:29:29

标签: scheme sicp

我长期以来对以下程序感到困惑。事实上,它是SICP 3.2的练习

;exercises 3.2
(define (make-monitored f)
  (define (monitor count)
    (define how-many-calls
      count)
    (define reset-count
      (set! count 0))
    (define (dispatch param)
      (cond ((eq? param 'how-many-calls) how-many-calls)
            ((eq? param 'reset-count) reset-count)
            (else (begin (set! count (+ count 1))
                         (f param)))))
    dispatch
    )
  (monitor 0))

(define (square x) (* x x))

> (define s (make-monitored square))
> (s 10)
100
> (s 'how-many-calls)
0
>

我的问题是,为什么输出"(s'多少次通话)" 0不是1? 我可以定义一个动态变化的值吗? (定义多少次调用计数) 我想要在计数发生变化时多次调用动态变化的值。

2 个答案:

答案 0 :(得分:2)

你缺少一些括号。这是代码的固定版本:

(define (make-monitored f)
  (define (monitor count)
    (define (how-many-calls)
      count)
    (define (reset-count)
      (set! count 0))
    (define (dispatch param)
      (cond ((eq? param 'how-many-calls) (how-many-calls))
            ((eq? param 'reset-count) (reset-count))
            (else (begin (set! count (+ count 1))
                         (f param)))))
    dispatch)
  (monitor 0))

答案 1 :(得分:2)

how-many-calls的定义不是您想要的。它被定义为一个常数值:

(define (monitor count)
  (define how-many-calls     ; defines how-many-calls as the (initial)
    count)                   ; value of count

这意味着,当您进入cond的第一个案例时,您总是会返回相同的值,即how-many-calls的值,这只是原始值 count的值,即0。

(define (dispatch param)
  (cond ((eq? param 'how-many-calls) how-many-calls)

reset-count存在类似的问题:

(define reset-count   ; defines reset-count as the value of
  (set! count 0))     ; (set! count 0), which is probably void
((eq? param 'reset-count) reset-count)  ; return the value of reset-count

正如Chris Jester-Young's answer指出的那样,您希望将how-many-calls定义为过程,并从cond子句中调用