[racket] Handling errors from in-directory - and handling errors more generally
Peter could roll his own in-directory recursive function in just a few line catching the relevant exceptions:
> (define (traverse d)
> (parameterize ([current-directory d])
> (define d (directory-list))
> (for-each (lambda (x)
> (printf "~a " x)
> (define p (with-handlers ([exn:fail:filesystem? void])
> (file-or-directory-permissions x)))
> (displayln p)
> (define n (build-path x))
> (when (and (directory-exists? n) (memq 'read p))
> (traverse (build-path x))))
> d)))
-- Matthias
On Oct 12, 2010, at 11:50 AM, Matthew Flatt wrote:
> 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.
>
> _________________________________________________
> For list-related administrative tasks:
> http://lists.racket-lang.org/listinfo/users