unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
* About exception handling again ...
@ 2020-08-02 18:05 Zelphir Kaltstahl
  2020-08-03  4:41 ` John Cowan
  0 siblings, 1 reply; 4+ messages in thread
From: Zelphir Kaltstahl @ 2020-08-02 18:05 UTC (permalink / raw)
  To: Guile User

Hello Guile Users!

In order to update the exception handling examples in my examples
repository
(https://notabug.org/ZelphirKaltstahl/guile-examples/src/master/exception-handling),
I've spend some time thinking about exception handling, what was written
on the mailing list and some things I read in the reference manual. I
think I understand a bit better now, but I still have some question
marks in my head:

1. Is there any situation, in which one would like to raise a
non-continuable exception / condition, and not unwind the stack? Would
that make sense in any situation?

2. My rationale for unwinding the stack is written in the comments in
the example code:

~~~~
  ;; From the Guile reference manual:

  ;; "[...] it’s often the case that one would like to handle an exception by
  ;; unwinding the computation to an earlier state and running the error handler
  ;; there. After all, unless the raise-exception call is continuable, the
  ;; exception handler needs to abort the continuation. To support this use
  ;; case, if with-exception-handler was invoked with #:unwind? #t is true,
  ;; raise-exception will first unwind the stack by invoking an escape
  ;; continuation (see call/ec), and then invoke the handler with the
  ;; continuation of the with-exception-handler call." --
  ;; https://www.gnu.org/software/guile/docs/master/guile.html/Raising-and-Handling-Exceptions.html

  ;; Here the exception is non-continuable, so according to the reference
  ;; manual, we need to call with-exception-handler with #:unwind? being set to
  ;; #t for normal exception handling. If we do not do this, a (different?)
  ;; non-continuable exception is raised.

  ;; Q: Why unwind the stack?

  ;; A:

  ;; If the execution cannot be continued (non-continuable exception) at the
  ;; point, where the exception is raised, it means, that in that context, there
  ;; was insufficient information to continue the execution in useful way.

  ;; Unwinding the stack means discarding stack frames of procedure calls. This
  ;; happens up to the point, where an exception handler is defined. The result
  ;; of unwinding the stack is, that we only leave intact the environment, which
  ;; was available when the exception handler was defined.

  ;; We have the knowledge at this point, that an exception occurred. That is
  ;; more than we knew, when we called the procedure, which raised the
  ;; exception. Furthermore the exception can contain information about the kind
  ;; of thing that went wrong. This information hand-over facility should be
  ;; used to give sufficient information to the exception handler, so that the
  ;; handler can continue execution in a useful way. The exception enables us to
  ;; store important information from the environment at the point where the
  ;; exception was raised. Then we have no need to keep the environment of the
  ;; point, where the exception was raised and can unwind the stack.
~~~~

Is this all correct?

3. What would be a code example for a continuable exception / condition
and what does the "continuing" there look like? I think the idea of
exception in my head is still influenced a lot by Python or other
languages, where it seems like all exceptions are non-continuable. (Is
that correct?)

4. Is there a situation, where one would like to raise a continuable
exception / condition, but also unwind the stack?

5. Are the updated examples correct usage of exception handling?

6. Why is it recommended to make use of (make-exception ...) instead of
the rnrs facilities in Guile? Wouldn't using rnrs stuff be more portable
to other Schemes?

7. I noted from the last discussion the following:

~~~~
In case of "non-continuable" exceptions the handler procedure given to
~with-exception-handler~ should not return. If it returns, then another
"non-continuable" exception will be raised when it tries to return.
~~~~

What does it mean for with-exception-handler to "return"? How can it not
return? Does this mean CPS like not returning, or does it mean "not
return a value"?

8. What would I need to do to the current updated examples, to make good
Guile 2.2.x examples?

Regards,
Zelphir

-- 
repositories: https://notabug.org/ZelphirKaltstahl




^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: About exception handling again ...
  2020-08-02 18:05 About exception handling again Zelphir Kaltstahl
@ 2020-08-03  4:41 ` John Cowan
  2020-08-03  7:53   ` tomas
  2020-08-03 23:17   ` Zelphir Kaltstahl
  0 siblings, 2 replies; 4+ messages in thread
From: John Cowan @ 2020-08-03  4:41 UTC (permalink / raw)
  To: Zelphir Kaltstahl; +Cc: Guile User

On Sun, Aug 2, 2020 at 2:05 PM Zelphir Kaltstahl <zelphirkaltstahl@posteo.de>
wrote:


> 1. Is there any situation, in which one would like to raise a
> non-continuable exception / condition, and not unwind the stack? Would
> that make sense in any situation?
>

I'm going to talk about Scheme in general, not Guile specifically.  There
are at least three use cases:

1) A reflective low-level debugger that can examine variables in the
current stack frame, which can't possibly work if the stack frame is gone.

2) A handler that wants to examine the dynamic environment in place when
the exception was raised.

3) A restart system that returns to the context of the raise and executes
recovery code, often chosen on the basis of interaction.  Frequently used
recovery actions include retrying the failed operation (on the assumption
that the external environment has changed), retrying the operation with one
or more different variables, and setting local variables to new values and
retrying.

A "Lisp debugger" is code that examines the available restarts and invokes
one of them, but Scheme doesn't have such a thing yet because it has no
restart system yet.  See <
https://github.com/johnwcowan/r7rs-work/blob/master/RestartsCowan.md>.  CL
has a restart system rather more complex than my proposal, which is based
on an earlier proposal by Taylor Campbell.


> Is this all correct?
>

I would say "correct but not complete".


> 3. What would be a code example for a continuable exception / condition
> and what does the "continuing" there look like? I think the idea of
> exception in my head is still influenced a lot by Python or other
> languages, where it seems like all exceptions are non-continuable. (Is
> that correct?)
>

Let's say a procedure wants to open a configuration file, but the
configuration file cannot be opened.  Raising a continuable exception
allows the handler to take some recovery action (perhaps it prompts the
user for the location of the config file) and return to the point where the
exception was raised.  Restarts extend this concept by providing a protocol
for the handler to communicate with the raiser, just as condition objects
are a protocol to let the raiser communicate with the handler.

In languages without continuable exceptions, such a retry must be done from
the handler level, which may imply re-executing a lot of code that was run
before the config file was wanted.  With continuable exceptions, this is
not necessary.

The `guard` special form basically emulates the behavior of {Python, JS,
Java, C#} style exception systems in cases where that behavior is
sufficient.


> 4. Is there a situation, where one would like to raise a continuable
> exception / condition, but also unwind the stack?
>

Not that I can think of.


> IWhat does it mean for with-exception-handler to "return"? How can it not
> return? Does this mean CPS like not returning, or does it mean "not
> return a value"?
>

The former.  An exception being raised non-continuably is really raised
continuably, but then if that returns, an exception that means "attempt to
continue from a non-continuable exception" is raised non-continuably.  If
you aren't careful in your handler to re-raise exceptions you don't
understand (normally with raise-continuable), this will obviously get into
an infinite loop.

(In CL the behavior of a handler is slightly different.  If it returns, the
exception is re-raised automatically. so in order to unwind the stack one
must use one of CL's three upward continuations:  block/return, tagbody/go,
or catch/throw.  The last is dynamically scoped, so it is usually the thing
to do in this context.  Handler-bind, like guard, is a convenience macro
for emulating stack-unwonding systems._



John Cowan          http://vrici.lojban.org/~cowan        cowan@ccil.org
He that would foil me must use such weapons as I do, for I have not
fed my readers with straw, neither will I be confuted with stubble.
                        --Thomas Vaughan (1650)


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: About exception handling again ...
  2020-08-03  4:41 ` John Cowan
@ 2020-08-03  7:53   ` tomas
  2020-08-03 23:17   ` Zelphir Kaltstahl
  1 sibling, 0 replies; 4+ messages in thread
From: tomas @ 2020-08-03  7:53 UTC (permalink / raw)
  To: guile-user

[-- Attachment #1: Type: text/plain, Size: 80 bytes --]

Hey,

thanks to you both for this enjoyable collateral learning :)

Cheers
-- t

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: About exception handling again ...
  2020-08-03  4:41 ` John Cowan
  2020-08-03  7:53   ` tomas
@ 2020-08-03 23:17   ` Zelphir Kaltstahl
  1 sibling, 0 replies; 4+ messages in thread
From: Zelphir Kaltstahl @ 2020-08-03 23:17 UTC (permalink / raw)
  To: John Cowan; +Cc: Guile User

Hello John!


On 8/3/20 6:41 AM, John Cowan wrote:
>
>
> On Sun, Aug 2, 2020 at 2:05 PM Zelphir Kaltstahl
> <zelphirkaltstahl@posteo.de <mailto:zelphirkaltstahl@posteo.de>> wrote:
>  
>
>     1. Is there any situation, in which one would like to raise a
>     non-continuable exception / condition, and not unwind the stack? Would
>     that make sense in any situation?
>
>
> I'm going to talk about Scheme in general, not Guile specifically. 
> There are at least three use cases:
>
> 1) A reflective low-level debugger that can examine variables in the
> current stack frame, which can't possibly work if the stack frame is gone.
>
> 2) A handler that wants to examine the dynamic environment in place
> when the exception was raised.
>
> 3) A restart system that returns to the context of the raise and
> executes recovery code, often chosen on the basis of interaction. 
> Frequently used recovery actions include retrying the failed operation
> (on the assumption that the external environment has changed),
> retrying the operation with one or more different variables, and
> setting local variables to new values and retrying.
>
> A "Lisp debugger" is code that examines the available restarts and
> invokes one of them, but Scheme doesn't have such a thing yet because
> it has no restart system yet.  See
> <https://github.com/johnwcowan/r7rs-work/blob/master/RestartsCowan.md>. 
> CL has a restart system rather more complex than my proposal, which is
> based on an earlier proposal by Taylor Campbell.
>  
>
>     Is this all correct?
>
>
> I would say "correct but not complete".
>  
>
>     3. What would be a code example for a continuable exception /
>     condition
>     and what does the "continuing" there look like? I think the idea of
>     exception in my head is still influenced a lot by Python or other
>     languages, where it seems like all exceptions are non-continuable. (Is
>     that correct?)
>
>
> Let's say a procedure wants to open a configuration file, but the
> configuration file cannot be opened.  Raising a continuable exception
> allows the handler to take some recovery action (perhaps it prompts
> the user for the location of the config file) and return to the point
> where the exception was raised.  Restarts extend this concept by
> providing a protocol for the handler to communicate with the raiser,
> just as condition objects are a protocol to let the raiser communicate
> with the handler.
>
> In languages without continuable exceptions, such a retry must be done
> from the handler level, which may imply re-executing a lot of code
> that was run before the config file was wanted.  With continuable
> exceptions, this is not necessary.
>
> The `guard` special form basically emulates the behavior of {Python,
> JS, Java, C#} style exception systems in cases where that behavior is
> sufficient.
>  
>
>     4. Is there a situation, where one would like to raise a continuable
>     exception / condition, but also unwind the stack?
>
>
> Not that I can think of.
>  
>
>     IWhat does it mean for with-exception-handler to "return"? How can
>     it not
>     return? Does this mean CPS like not returning, or does it mean "not
>     return a value"?
>
>
> The former.  An exception being raised non-continuably is really
> raised continuably, but then if that returns, an exception that means
> "attempt to continue from a non-continuable exception" is raised
> non-continuably.  If you aren't careful in your handler to re-raise
> exceptions you don't understand (normally with raise-continuable),
> this will obviously get into an infinite loop.
>
> (In CL the behavior of a handler is slightly different.  If it
> returns, the exception is re-raised automatically. so in order to
> unwind the stack one must use one of CL's three upward continuations: 
> block/return, tagbody/go, or catch/throw.  The last is dynamically
> scoped, so it is usually the thing to do in this context. 
> Handler-bind, like guard, is a convenience macro for emulating
> stack-unwonding systems._
>
>
>
> John Cowan          http://vrici.lojban.org/~cowan      
>  cowan@ccil.org <mailto:cowan@ccil.org>
> He that would foil me must use such weapons as I do, for I have not
> fed my readers with straw, neither will I be confuted with stubble.
>                         --Thomas Vaughan (1650)
>
Thank you for the examples! They explain, why one would want to have the
flexibility to decide whether to unwind or not to unwind.

I'll try to perhaps add a phrase like "There are some scenarios, in
which not unwinding makes sense, for example …".

I'm glad, that my understanding was not completely wrong.

Regards,
Zelphir



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2020-08-03 23:17 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-02 18:05 About exception handling again Zelphir Kaltstahl
2020-08-03  4:41 ` John Cowan
2020-08-03  7:53   ` tomas
2020-08-03 23:17   ` Zelphir Kaltstahl

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).