Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does PLTScheme Catch errors?

I am amazed by the "error" function in PLTScheme. If I have a division by zero, it doesnt do any other recursion and just comes out of the call stack and give me an error.

Is there an implicit continuation before all the functions? Does the error throw away the call stack? Does anybody have any idea about this?

like image 607
unj2 Avatar asked Oct 13 '09 01:10

unj2


1 Answers

In PLT Scheme, the procedure error raises the exception exn:fail, which contains an error string. There is no "implicit catch" for all defines. Look at the following sample:

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

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

Execute the above script from the command line and you will see the interpreter existing after printing something like

/: division by zero

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

If an exception is not handled within the user program, it is propagated up to the core interpreter where a default handler deals with it, i.e print the exception and exit. In other words, the interpreter just says, "an exception was raised and I don't know how to deal with it, so I am quiting". This is not much different from how the JVM or some other virtual machine handle exceptions.

To learn more about PLT Scheme's exception handling mechanism, please read about with-handlers and dynamic-wind in the MzScheme Language Manual. Using these, you can even emulate Java's try-catch-finally block.

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

Here is the syntax extension that made the above possible:

;; 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 ...)))))
like image 54
Vijay Mathew Avatar answered Sep 24 '22 03:09

Vijay Mathew