Exercise 3.2. In software-testing applications, it is useful to be able to count the number of times a given procedure is called during the course of a computation. Write a procedure make-monitored that takes as input a procedure, f, that itself takes one input. The result returned by make-monitored is a third procedure, say mf, that keeps track of the number of times it has been called by maintaining an internal counter. If the input to mf is the special symbol how-many-calls?, then mf returns the value of the counter. If the input is the special symbol reset-count, then mf resets the counter to zero. For any other input, mf returns the result of calling f on that input and increments the counter. For instance, we could make a monitored version of the sqrt procedure:
(define s (make-monitored sqrt))
(s 100)
10
(s 'how-many-calls?)
1
过程的参数可以当做过程的内部变量。除此之外如果还需要内部变量,则需要使用 let 配合 lambda 来定义一个过程。
在本题中, ``make-monitored`` 接受一个过程 f 作为参数,返回另外一个过程。这个返回的过程将接受
'how-many-calls?
,返回 f 调用了多少次;'reset-count
, f 调用次数清零;- f 的参数,返回 (f arg);
(define make-monitored
(let ((how-many 0))
(lambda (f)
(lambda (arg)
(cond ((eq? arg 'how-many-calls?)
how-many)
((eq? arg 'reset-count)
(set! how-many 0))
(else
(begin
(set! how-many (+ 1 how-many))
(f arg))))))))
(define s (make-monitored sqrt))
结果为:
1 ]=> (s 100)
;Value: 10
1 ]=> (s 'how-many-calls?)
;Value: 1
1 ]=> (s 1024)
;Value: 32
1 ]=> (s 'how-many-calls?)
;Value: 2
1 ]=> (s 'reset-count)
;Value: 2
1 ]=> (s 'how-many-calls?)
;Value: 0