views:

182

answers:

1

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?

+4  A: 

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 ...)))))
Vijay Mathew
This was not what I was looking for. In Scheme, most of the functions automatically check division by zero and other errors, how does that happen? Is the catching implicit in all defines?
kunjaan
@kunjaan I have updated my answer.
Vijay Mathew