0

I have been confused about the following program for a long time. in fact, it's a exercise of 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
>

my question is , why the output of "(s 'how-many-calls)" is 0 not 1? can I define a value dynamicly changed? (define how-many-calls count) I want the value of how-many-calls dynamic change when count changes.

user3754786
  • 57
  • 1
  • 6

2 Answers2

2

You are missing some parentheses. Here's a fixed version of the code:

(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))
C. K. Young
  • 219,335
  • 46
  • 382
  • 435
  • This doesn't quite explain what the problem was though. I.e., that `how-many-calls` was simply defined as the initial value of `count`, so that the `((eq? param 'how-many-calls) how-many-calls)` just *returned* the value of `how-many-calls` (the *initial* value of `count`). – Joshua Taylor Jun 19 '14 at 20:38
  • @JoshuaTaylor That, and `reset-count` was simply an unspecified value (being the return value of `set!`, and thus not resetting the count at all ;-)). (Oh, I noticed your answer covered that. Have a +1.) (Of course, I agree with your comment; I wanted the OP to do a diff between their version and mine and figure out where the differences were.) – C. K. Young Jun 19 '14 at 21:24
  • thanks guys! `(define how-many-calls (begin (print 'a) count))` when the evaluation expression be executed, on the first time I call (make-montoried f)? I heard Scheme is 'pass by value', So that's why count is always 0 , not dynamic retrieved from run-time? – user3754786 Jun 20 '14 at 03:05
  • @user3754786 It's not really anything to do with pass by value, bur rather it's whether you're defining a procedure or not. `(define x 82)` defines a variable with the value 82. `(define x (lambda () 82))` defines a variable with a value that is a procedure that returns 82. It can be abbreviated as `(define (x) 82)`. Since it's a procedure of no arguments that returns the value of a variable, the two look very similar. For cases where's the difference is clearer, consider `(define square (lambda (x) (* x x)))` and `(define (square x) (* x x))`. Those are the same, but – Joshua Taylor Jun 20 '14 at 15:12
  • 1
    @user3754786 `(define square (* x x))` is either a constant (if `x` is defined at that point) or an error (if it's not). – Joshua Taylor Jun 20 '14 at 15:15
2

The definition of how-many-calls isn't what you want. It's being defined as a constant value:

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

This means that when you get into the first case of your cond, you're always returning the same value, viz., the value of how-many-calls, which is just the original value of count, i.e., 0.

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

There's a similar problem with 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

As Chris Jester-Young's answer points out, you want to define how-many-calls as procedures, and to call them from the cond clauses.

Community
  • 1
  • 1
Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353