2

像无限循环这样的长期功能:

> (define appendInf
      (lambda (lst)
        (appendInf (cons 1 lst)))

在 Chez Scheme 中,make-engine 可以实现 tick 后停止:

> (define eng
    (make-engine 
      (lambda ()
        (appendInf '()))))

当然,在 lst 的范围内,我在以下情况下会出错:

> (eng 50
        list
        (lambda (new-eng)
          (set! eng new-eng)
          (length lst)))
Exception: variable lst is not bound

如果我想在达到时间限制时在 appendInf 中获取值 'lst',我使用 set!:

> (define lst '())
> (define appendInf
      (lambda (ls)
        (set! lst (cons 1 ls))
        (appendInf lst)))

现在我可以得到:

> (eng 50
       list
       (lambda (new-eng)
         (set! eng new-eng)
         (length lst)))
8

因此,对于我要跟踪的函数中的每个变量,都需要添加一个全局变量,并通过添加 (set!...) 再进行一个转换。

  1. 这是处理任何封闭变量的正确方法吗?
  2. 如果是 1,在方案中是否有更好的方法来实现这一目标?
  3. 是否有任何编程语言可以更轻松地实现这种调试?
4

1 回答 1

0

出色地。我正在使用球拍,它有一个非常好的调试器,可以执行标准 r6rs 和非标准球拍。

;; macro to do the heavy work
(define-syntax recdb
  (syntax-rules ()
    ((_ thunk fun a1 ...)
     (let ((orig-fun fun)(ethunk thunk))
       (fluid-let ((fun (lambda args 
                          (if (ethunk)
                              (apply orig-fun args) ;; set breakpoint on this
                              (apply orig-fun args)))))
         (fun a1 ...))))))

;; a time-thunk generator
(define (period-sec sec)
  (let ((time-done (+ sec (current-seconds))))
    (lambda ()
      (if (< time-done (current-seconds))
          (begin 
            (set! time-done (+ sec (current-seconds)))
            #t)
          #f))))

;; a round-thunk generator
(define (rounds n)
  (let ((rounds-to-go n))
    (lambda ()
      (if (zero? rounds-to-go)
          (begin
            (set! rounds-to-go (- n 1))
            #t)
          (begin
            (set! rounds-to-go (- rounds-to-go 1))
            #f)))))

;; my never ending procedure
(define (always n)
  (always (+ n 1)))

;; one of the ones below to implement 
(recdb (rounds 10) always 0))
(recdb (period-sec 1) always 0)

;; functions with auxillary procedures need to have their gut changed for it to work
(define (fib n)
  (define (fib-aux n a b)
    (if (= n 0)
        a
        (fib-aux (- n 1) b (+ a b))))
  (recdb (period-sec 2) fib-aux n 0 1))

 ;; trying it
 (fib 200000)

现在。只需运行调试器并设置断点(在宏中右键单击表达式并选择“此时暂停”),它在代码中指示,您可以每 x 秒或 x 次检查变量。

调试愉快:)

于 2013-03-04T18:53:56.553 回答