guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: "Missing" libraries/concepts found in other languages/ecosystems?


From: Chris Vine
Subject: Re: "Missing" libraries/concepts found in other languages/ecosystems?
Date: Sun, 12 Jul 2020 20:14:23 +0100

On Sun, 12 Jul 2020 18:08:33 +0200
Catonano <catonano@gmail.com> wrote:
> Il giorno sab 11 lug 2020 alle ore 12:14 Chris Vine <vine35792468@gmail.com>
> ha scritto:
> 
> > On Sat, 11 Jul 2020 02:19:43 +0200
> > Zelphir Kaltstahl <zelphirkaltstahl@posteo.de> wrote:
> > [snip]
> > > I would be glad, if any non-optimal example was extended or updated by a
> > > more knowledgeable person or I was told what I could improve in some
> > > example. The examples in the repository are only, what I was able to
> > > understand and I often find myself looking up, how to do something again.
> > >
> > > If anyone wants to take any example and put it in the docs, go ahead.
> > > Only don't think that my examples are the last word on how to do things.
> > > Far from it!
> > >
> > > About the exceptions thing: Aha! I should look into that again. I
> > > thought the "conditions" thing was already pretty cool and useful. Once
> > > an exception happens, you can react on it. I did not understand the
> > > "call/ec helper" part, but perhaps I can understand it, when I check the
> > > docs for the new exceptions in Guile 3.
> >
> > The issue is that "non-continuable" in "non-continuable exception" does
> > not mean an exception that the program cannot survive, it means an
> > exception for which, after handling, control cannot return to the point
> > at which the exception was raised[1].  (To answer the question in your
> > following email, continuable exceptions are in some sense analogous to
> > common lisp restarts.)  Most guile exceptions are non-continuable.  The
> > point arising from this is that in the case of a non-continuable
> > exception the handler procedure passed to with-exception-handler must
> > not return, or a &non-continuable exception will be raised when
> > control does attempt to return.
> >
> > With R6RS/R7RS's with-exception-handler, for non-continuable exceptions
> > the handler procedure should normally therefore either invoke a call/ec
> > continuation object to unwind the stack to the point where the
> > exception is handled, or it should (after it has done what it is
> > intended to do) re-raise the exception to be handled and/or unwound
> > elsewhere.  Guile-3.0's with-exception-handler procedure will do the
> > former for you automatically if you set its #:unwind? argument to
> > true.  The nearest to guile-2.2's catch expression in guile-3.0's
> > exception system is to use with-exception-handler with #:unwind? set
> > as #t.  R6RS/R7RS's guard form is a wrapper for this which also
> > incorporates a cond form to enable different exception types to be
> > handled by different handlers.
> >
> > I therefore suggest that your first example using
> > with-exception-handler should set #:unwind? to #t so that the program
> > does not end with a &non-continuable exception.  I also suggest that,
> > if intended for guile-3.0 and not guile-2.2, you should use guile's
> > exception objects rather than R6RS conditions (basically you use
> > 'make-exception' instead of 'condition' - the two are in effect the
> > same).
> >
> 
> 
> If it can be of any help, I applied your suggestions to the original
> example
> 
> This is supposed to be compatible with Guile 3.x only
> 
> Here it is (a question follows)
> 
> (define even-simpler-display
>   (lambda (sth)
>     (display
>      (simple-format
>       #f "~a\n" sth))))
> 
> 
> (define divide
>   (lambda (a b)
>     (cond
>      [(= b 0)
>       (raise-continuable
>        (make-exception
>         (make-exception-with-message "division by zero")
>         (make-exception-with-irritants (list a b))
>         (make-exception-with-origin 'divide)))]
>      [else
>       (/ a b)])))
> 
> 
> (with-exception-handler
>     (lambda (conditions-or-value)
>       (even-simpler-display
>        ;; We can get the simple exceptions from a compound exception with
> the
>        ;; `simple-exceptions` getter.
>        (simple-exceptions conditions-or-value)))
>   (lambda ()
>     (divide 2 0))
>     #:unwind? #t)
> 
> I run this in the REPL and it seems to work
> 
> The question, now, is:
> 
> say that the exception handler knows (somehow) that the correct divisor is
> 1 rather than 0
> 
> So we are saying that this exception is continuable
> 
> How would we continue ?
> 
> Can "divide" return as if it had been called with 1 as its second argument ?
> 
> Or have I misunderstood ?
> 
> How would you go about that ?

First, you would need to have #:unwind? set to #f (the default) so that
the stack doesn't unwind, otherwise the stack is unwound to the dynamic
context in which with-exception-handler was called.

Secondly, if the handler returns and #:unwind? is set to #f then
raise-continuable will return with the value returned by the handler.
So this:

  (with-exception-handler
      (lambda (x) (+ x 3))
    (lambda () (+ (raise-continuable 10) 6)))

will evaluate to 19: the variable 'x' in the handler will be bound to
the value raised, which in this case is a number (10), the handler will
accordingly return 13, and 6 is added to the value returned by the
handler.  (Here the exception raised is an integer and not a guile
exception object in order to demonstrate the principle, but the same
point applies if an exception object is raised.)

With that format you should be able to tell the code committing the
divide by 0 error what to do with respect to the divisor.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]