title: More careful exceptions in Guile
date: 2015-09-05 18:15
author: Christine Lemmer-Webber
tags: guile, hacking
slug: guile-errors
---
So as I've probably said before, I've been spending a lot more time
hacking in [Guile](https://www.gnu.org/software/guile/guile.html)
lately. I like it a lot!

However, there is one thing that really irks me: error handling. Though
a programmer in Guile has a lot of flexibility to define their own error
handling mechanisms, really I think a language should be providing good
builtin ways of doing so. Guile does provide some builtin methods, but I
have problems with both of them.

The first is the more egregious of the two, and is a procedure known
simply as
[error](https://www.gnu.org/software/guile/manual/html_node/Error-Reporting.html#Error-Reporting),
which takes one argument: a string describing what went wrong. Usage
looks like so:

``` scheme
(if (something-bad? thing)
  (error "You shouldn't have done that!"))
```

This is fast to toss through your code without thinking, but at serious
cost. The problem is that this follows the ["diaper
pattern"](http://mike.pirnat.com/2009/05/09/the-diaper-pattern-stinks/)
(or "diaper antipattern?"). Guile provides a
[catch](https://www.gnu.org/software/guile/manual/html_node/Catch.html#Catch)
procedure, but if you try catching these errors, they are all thrown
with the "misc-error" symbol, and there is no way to catch the *right*
errors.

``` scheme
(catch 'misc-error
  ;; the code we're running
  (lambda ()
    (let ((http-response (get-some-url)))
      (if http-response
          ;; all went well, continue with our webby things
          (do-web-things http-response)
          ;; Uhoh!
          (error "the internet's tubes are filled"))))
  ;; The code to catch things
  (lambda _ (display "sorry, someone broke the internet\n")))
```

But wait... what if the user gave a keyboard interrupt and instead your
database execution code caught it instead? I you can't catch errors
precisely, things might bubble to the wrong place.

This is not an abstract problem; this happened to me in an extremely
well written Guile program, [Guix](https://www.gnu.org/software/guix/):
I was working on adding a new package and had screwed up the definition,
so somewhere up the chain Guix threw an error about my malformed
package, but I didn't know... instead, when I was attempting to run the
"guix package" command to test out my command, suddenly the "guix
package" command disappeared entirely. Whaaaaat? I did some debugging
and found a (catch 'misc-error) in the command line arguments handling
code. Whew! Well, that usage of "(error)" got replaced with some more
careful code, but what if I couldn't find it, or was a more green
developer?

So, luckily, Guile *does* provide a better exception handling system,
mostly. There's
[throw](https://www.gnu.org/software/guile/manual/html_node/Throw.html#Throw),
which looks a bit like this in your code:

``` scheme
(catch 'http-tubes-error
  ;; the code we're running
  (lambda ()
    (let ((http-response (get-some-url)))
      (if http-response
          ;; all went well, continue with our webby things
          (do-web-things http-response)
          ;; Uhoh!
          (throw 'http-tubes-error "the internet's tubes are filled"))))
  ;; The code to catch things
  (lambda _ (display "sorry, someone broke the internet\n")))
```

Okay, great! This is much more specific, yay!

Except... it still kind of bothers me. Maybe I'm being *overly* pedantic
here, but what if you and I both had 'json-error exceptions in our own
separate libraries? The problem is (unlike in common lisp) there aren't
module-specific symbols in Guile! This means we could catch someone
else's 'json-error when we really wanted to catch our own.

Okay, maybe this is rare, but I really don't like running into these
kinds of problems. I want my exception symbols to be unique per package,
damnit!

So in the interest of doing so, let me present you with a terrible hack
of scheme code (which like all other code content in this blogpost, I
both waive under [CC0 1.0
Universal](https://creativecommons.org/publicdomain/zero/1.0/deed.en)
(and also do waive any potential patent "rights") and also release under
LGPLv3 or later, your choice):

``` scheme
(define-syntax-rule (define-error-symbol error-symbol)
  (define error-symbol
    (gensym 
     ;; gensym can take a prefix
     (symbol->string (quote error-symbol)))))
```

Okay, it's kind of hacky, but what this does is give you a nice
convenient way to define *unique* symbols. (*Edit:* turns out gensym can
take a prefix, so the above code is even easier and less hacky now!
Thanks for the tip, taylanub!) You can use it like so:

``` scheme
(define-error-symbol http-tubes-error)

(catch http-tubes-error
  ;; the code we're running
  (lambda ()
    (let ((http-response (get-some-url)))
      (if http-response
          ;; all went well, continue with our webby things
          (do-web-things http-response)
          ;; Uhoh!
          (throw http-tubes-error "the internet's tubes are filled"))))
  ;; The code to catch things
  (lambda _ (display "sorry, someone broke the internet\n")))
```

See? All you have to do is do a simple definition above and you have a
unique-per-your-program error symbol (thanks to the gensym). Now if
users want to catch your errors, but *only* your errors, they can import
the error symbol directly from your package.

So the lesson from this post is: if you're going to use exceptions in
your code, please be careful... and specific!

*Update:* Apparently I can't be the only one who finds the need for
this; turns out that prompts (which have a similar "unwinding" property
to exceptions) also take symbols, but usefully there's (make-prompt-tag)
which does pretty much exactly the same thing as define-error-symbol
above. So I must not be totally crazy!
