[racket] Handling errors from in-directory - and handling errors more generally
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.