问题描述
(define tolerance 0.01)
(define (close-enough? x y) (< (abs (- x y)) 0.001))
(define (fixed-point function starting-guess)
(define iter-count 0)
(define (evaluate num)
; these lines increment the counter using set!
(set! iter-count (+ iter-count 1))
(display iter-count) (display " - ") (display num) (display "\n")
(let ((next-num (function num)))
(if (close-enough? num next-num)
next-num
(evaluate next-num))))
(evaluate starting-guess))
(fixed-point cos 1.0)
这样做的正确方法是什么?目前我已经添加了一个 define
和一个 set!
,因为我找不到让 let
工作的方法。有没有办法用 let
做到这一点,或者有什么建议的方法来做到这一点?
(define (fixed-point function starting-guess)
(define (evaluate num iteration-num)
(display iteration-num) (display " - ") (display num) (display "\n")
(let ((next-num (function num)))
(if (close-enough? num next-num)
next-num
(evaluate next-num (+ 1 iteration-num)))))
(evaluate starting-guess 0))
解决方法
就像 num
一样,您只需向循环函数添加一个参数即可:
(define (fixed-point function starting-guess)
;; prints progress
(define (print-progress iter-count)
(display iter-count)
(display " - ")
(display num)
(newline))
;; main calculating loop
(define (evaluate num iter-count)
(print-progress iter-count)
(let ((next-num (function num)))
(if (close-enough? num next-num)
next-num
(evaluate next-num (+ iter-count 1)))))
;; start process with iter-count 1 since
;; we do increments after display
(evaluate starting-guess 1))
请注意,您的此版本开始显示 0
,而您的 set!
版本以 1
开头。我通过从 1
而不是 0
开始来弥补这一点。
您可以通过将功能添加到 fixed-point
来完全避免 function
的副作用:
;; pure functional fixed-point
(define (fixed-point function starting-guess)
(define (evaluate num)
(let ((next-num (function num)))
(if (close-enough? num next-num)
next-num
(evaluate next-num))))
(evaluate starting-guess))
;; makes a version of function that
;; reports its first argument and
;; number of times it's been called
(define (count-and-brag-calls f)
;; brag does whatever and
;; return the value
(define (brag v c)
(display c)
(display " - ")
(display v)
(newline)
v)
;; actual implementation
(let ((count 0))
(lambda (n)
(set! count (+ count 1))
(brag (f n) count))))
;; with verbose output
(fixed-point (count-and-brag-calls cos) 1.0)
;; without side effects gives exact same result without output
(fixed-point cos 1.0)
,
对于最小的编辑,只需将计数器的定义(绑定)移动到顶层,并在每次你之前重置计数器给fixed-point
打电话:
(define iter-count 0) ;; here
(define (fixed-point function starting-guess)
;; (define iter-count 0) ;; commented-out
....
....
)
(begin
(set! iter-count 0)
(fixed-point ... ... ))