[plt-scheme] Re: exception handling

From: Eli Barzilay (eli at barzilay.org)
Date: Sat May 16 18:17:21 EDT 2009

On May 16, wooks wrote:
> 
> Don't understand the explanation in the docs. Looks complicated and
> what I want to do is real simple. Ignore the exception and carry on.

(with-handlers ([(lambda (exn) #t) (lambda (exn) 'whatever)])
  (* 3 "4"))


> Don't understand why I need with-handlers since I don't want to do
> anything with the exception.

`with-handlers' allows you to catch the exception and do whatever you
want with it -- you don't have to actually use it, like the above.
But see what I said in the other message -- since it catches all
errors, it will catch errors in your own code too.  A common mistake
is to try to use it, for example, to remove a temporary file where
nothing bad happens if it's not removed.  Using the above:

  > (define (delete-files files)
      (for-each delete-file files))
  > (define (delete-temp-files)
      (with-handlers ([(lambda (exn) #t) (lambda (exn) 'whatever)])
        (delete-files "foo.txt" "bar.txt" "baz.txt")))
  > (delete-temp-files)
  whatever

Looks fine right?  Well, following my advice in the previous email,
I should make the `with-handlers' as specific as possible.  In this
case, I should really ignore only `exn:fail:filesystem?' exceptions.
If I do that, then I'd find that I had a real bug in the code:

  > (define (delete-files files)
      (for-each delete-file files))
  > (define (delete-temp-files)
      (with-handlers ([exn:fail:filesystem? (lambda (exn) 'whatever)])
        (delete-files "foo.txt" "bar.txt" "baz.txt")))
  > (delete-temp-files)
  procedure delete-files: expects 1 argument, given 3: "foo.txt"
  "bar.txt" "baz.txt"

The other thing that I said is good is to put the with-handlers around
as little code as possible -- in this case, this would mean moving it
to the `delete-files' function, or even around each file deletion:

  > (define (delete-files files)
      (for ([file files])
        (with-handlers ([exn:fail:filesystem? (lambda (exn) 'whatever)])
          (delete-file file))))

This would also avoid masking out my real bug, since
`delete-temp-files' doesn't ignore errors in its body.

Even better is to not ignore the exception; for example, this code
will report the error, but will continue to run:

(list
  1
  (with-handlers ([exn? (lambda (exn)
                          ((error-display-handler) (exn-message exn) exn)
                          'whatever)])
    (* 2 "3"))
  4)

-- 
          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                  http://www.barzilay.org/                 Maze is Life!


Posted on the users mailing list.