[racket] Handling errors from in-directory - and handling errors more generally

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Tue Oct 12 11:50:20 EDT 2010

At Tue, 12 Oct 2010 14:48:49 +0100, Peter Kiggins wrote:
> [I am completely new to both Scheme and racket, so if my questions are
> Looking at traversal of a file tree led me to in-directory.  The
> problem is that as soon as it hits a directory it cannot search
> (permissions, whatever...) it drops out with an exception.  For
> example:
> (for ([e (in-directory "/Users/lucas")])
>   (printf "~a\n" e))
> /Users/lucas/.CFUserTextEncoding
> /Users/lucas/.DS_Store
> /Users/lucas/Desktop
> directory-list: could not open "/Users/lucas/Desktop" (Permission
> denied; errno=13)
> I'd like to be able to catch the error, change the output, and
> continue pulling names:
> (for ([e (safe-in-directory "/Users/lucas")])
>    (printf "~a\n" e))
> /Users/lucas/.CFUserTextEncoding
> /Users/lucas/.DS_Store
> /Users/lucas/Desktop[permission denied]
> /Users/lucas/morefiles
> ...
> ...
> How is in-directory meant to be used, so that it re-starts after an
> error? 

I don't think there's a way currently to have `in-directory' continue
at that point.

> In general, what is idiomatic for catching exceptions, re-trying after
> an exception, running finalise code?  Is there an equivalent to Clisp
> restarts?

No particular restart system built into the exception system. Code that
raises an exception can include a continuation in the exception to
allow a restart, and the exception raised for an asynchronous break
(which is usually triggered when you hit Ctl-C) does that. But
`directory-list' as used by `in-directory' doesn't include a restart
continuation in the exception record that it creates, and
`in-directory' doesn't particularly catch exceptions or introduce any
restart continuations.

Among Racket procedures that support specific failure handling, most do
so through an optional failure-thunk argument. For example, `hash-ref'
and `file-or-directory-modify-seconds' accept failure thunks. The
handlers in those cases just produce an alternate result --- the same
thing could be accomplished by catching an exception --- as opposed to
continuing internally. So, I think there's not really much precedent
for this in the Racket API.

Posted on the users mailing list.