【问题标题】:How to add a counter to this scheme function如何向此方案功能添加计数器
【发布时间】:2021-05-10 22:19:50
【问题描述】:

我想添加一个计数器,以便查看迭代运行了多少次:

(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)

这样做的正确方法是什么?目前我已经添加了defineset!,因为我无法找到让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))

【问题讨论】:

    标签: recursion scheme lisp sicp


    【解决方案1】:

    就像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 来弥补这一点。

    您可以通过将功能添加到function 来完全避免fixed-point 的副作用:

    ;; 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)
    

    【讨论】:

    • 谢谢,“吹牛”是什么意思?我从来没有听说过在那种情况下这样使用它。
    • @David542 吹牛:用过度的骄傲或虚荣来说话。我发现它是一个令人愉快的名字,因为没有的函数只会完成它的工作,而添加 count-and-brag 将“吹嘘”每次调用它时被调用的次数以及当前的返回值 :-) BTW:我是挪威人而不是以英语为母语的人。
    【解决方案2】:

    对于最小的编辑,只需将 counter 的 定义(绑定)移动到顶层,并在每次 you 之前重置 counter拨打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 ... ... ))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多