Как происходит ошибка PLTScheme Catch? - PullRequest
5 голосов
/ 13 октября 2009

Я поражен функцией "ошибка" в PLTScheme. Если у меня деление на ноль, оно не выполняет никакой другой рекурсии, а просто выходит из стека вызовов и выдает ошибку

Есть ли неявное продолжение перед всеми функциями? Ошибка выбрасывает стек вызовов? У кого-нибудь есть идеи по этому поводу?

1 Ответ

6 голосов
/ 13 октября 2009

В схеме PLT процедура ошибка вызывает исключение exn: fail , которое содержит строку ошибки. Не существует «неявного улова» для всех определений. Посмотрите на следующий образец:

;; test.ss
(define (a d)
  (printf "~a~n" (/ 10 d)))

(a 0) ;; The interpreter will exit here.     
(printf "OK~n")

Запустите приведенный выше скрипт из командной строки, и вы увидите, что интерпретатор существует после печати чего-то вроде

/: division by zero

 === context ===
/home/user/test.ss:1:0: a

Если исключение не обрабатывается в пользовательской программе, оно распространяется до основного интерпретатора, где с ним работает обработчик по умолчанию, то есть печатает исключение и завершается. Другими словами, переводчик просто говорит: «Возникло исключение, и я не знаю, как с ним бороться, поэтому я ухожу». Это не сильно отличается от того, как JVM или другая виртуальная машина обрабатывает исключения.

Чтобы узнать больше о механизме обработки исключений в PLT-схеме, прочитайте о с обработчиками и dynamic-wind в MzScheme Language Manual Используя их, вы даже можете эмулировать Java-блок try-catch-finally.

(define (d a b)
  (try
   (printf "~a~n" (/ a b))
   (catch (lambda (ex)
            (printf "Error: ~a" ex)))
   (finally 
    (if (> b -2) 
      (d a (sub1 b))))))

Вот расширение синтаксиса, которое сделало возможным вышеуказанное:

;; try-catch-finally on top of with-handlers and dynamic-wind.

(define-syntax try
  (syntax-rules (catch finally)
    ((_ try-body ... (catch catch-proc))
     (with-handlers (((lambda (ex) #t)
              (lambda (ex) 
            (catch-proc ex))))
            (begin
              try-body ...)))
    ((_ try-body ... (catch catch-proc) (finally fin-body ...))
     (dynamic-wind
     (lambda () ())

     (lambda ()
       (with-handlers (((lambda (ex) #t)
                (lambda (ex) 
                  (catch-proc ex))))
              (begin
                try-body ...)))

     (lambda () fin-body ...)))
    ((_ try-body ... (finally fin-body ...))
     (dynamic-wind
     (lambda () ())

     (lambda () try-body ...)

     (lambda () fin-body ...)))))
...