Incidentally, sorry for the mangled formatting / narrow margins that
my emails keep having.  I'm not doing that, it's coming from GMail.

On Tue, May 15, 2018 at 10:06 AM, David Storrs <[email protected]> wrote:
> On Tue, May 15, 2018 at 1:28 AM, Matthew Butterick <[email protected]> wrote:
>> To add to your pile of options, because you said "certain error conditions":
>> perhaps you might `raise` an exception in the db code that gets caught by
>> the network code (using `with-handlers`). In this way the dependency only
>> runs one direction (network module imports db module) but the db module can
>> still propagate messages to the network module (by going "backward" through
>> the existing calling chain with an exception, rather than "forward" by
>> calling into the db module).
>>
>> Here is a toy example of a `db` module that keeps kicking back an exception
>> to a `network` module until it gets zero, no circularity needed:
>>
>> #lang racket
>>
>> (module db racket
>>   (provide f)
>>   (define (f val)
>>     (if (zero? val)
>>         'finally-a-zero!
>>         (raise val))))
>>
>> (module network racket
>>   (require (submod ".." db))
>>   (let loop ([maybe-err-int #f])
>>     (with-handlers ([integer? loop])
>>       (when maybe-err-int
>>         (displayln (number->string maybe-err-int)))
>>       (f (random 10)))))
>>
>> (require 'network)
>
> Brilliant!  That's perfect, thank you.
>
> On that subject, I note the existence of handy/try on the package
> server.  It provides a macro for exception handling that combines
> 'with-handlers' and 'dynamic-wind' while having better end weight than
> the former.  It comes in several flavors, the most general of them
> being:
>
> (try [(do database thing here)  (write files to disk)]
>       [pre (mark records in DB as locked and lock files on disk before
> the main body of the try runs)]
>       [catch (exn:fail:db (lambda (e) (displayln (~a "Database failed
> with message: " (exn-message e)))))
>                  (exn:fail:filesystem (lambda (e) (displayln (~a
> "failed to write file: " (exn-message e)))))]
>       [finally (unlock records in DB, unlock files)])
>
> This reduces to:
>
> (with-handlers ([(exn:fail:db (lambda (e) (displayln (~a "Database
> failed with message: " (exn-message e)))))]
>                          [(exn:fail:filesystem (lambda (e) (displayln
> (~a "failed to write file: " (exn-message e)))))])
>   (dynamic-wind
>      (thunk (mark records in DB as locked and lock files on disk
> before the main body of the try runs))
>      (thunk (do database thing here)  (write files to disk))
>      (thunk (unlock records in DB, unlock files))))
>
> I believe the 'try' version to be better because it is syntactically
> simpler, explicitly labels the different parts of the 'dynamic-wind'
> instead of requiring that you know what they are, and provides better
> end weight in the 'with-handlers' -- the body of the code is up front
> so you know what is supposed to happen, while the error handling /
> preflight / cleanup are tucked away at the end so that you already
> know the context and don't need to think about them while dealing with
> the happy path.
>
> The 'pre', 'catch', and 'finally' blocks are all optional and leaving
> them out simply defatalizes and returns the exception if there is one.
> I should create a version that lets you put 'pre' ahead of the body if
> that's what you want, but I haven't done that yet.
>
>
>>
>>
>> On May 14, 2018, at 10:28 AM, David Storrs <[email protected]> wrote:
>>
>> This worked fine until now, but I've gotten to a point where they're
>> circular -- the network code needs to receive the chunk and then
>> forward it to the DB code, but if certain error conditions come up
>> then the DB code needs to tell the network code to re-request the
>> data.
>>
>> There's various ways I could work around this (simplest being to put
>> all the functions in one file), but I'm wondering if there's a
>> recommended way?  C would solve this with a .h file.  Perl would solve
>> it with function prototypes (or simply be able to sort it out without
>> intervention).  What is the preferred Racket way, or am I simply not
>> thinking about it correctly?
>>
>>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to