From: Tobias C. Rittweiler
Subject: Condition System; handlers simultaneously matching in the same binding form; CLHS 9.1.4
Date:
Message-ID: <87d4lh3dsw.fsf@freebits.de>
Hi,
CLHS 9.1.4 states:
Once a handler in a handler binding form (such as handler-bind or
handler-case) has been selected, all handlers in that form become
inactive for the remainder of the signaling process. While the
selected handler runs, no other handler established by that form is
active. That is, if the handler declines, __no other handler established
by that form will be considered for possible invocation__.
However, I don't understand the behaviour of the following snippet in
light of the above paragraph:
(handler-bind ((error #'(lambda (e) (format t "ERROR: ~S~%" e)))
(condition #'(lambda (c) (format t "CONDITION: ~S~%" c))))
(signal 'error))
; ERROR: #<ERROR {A9F68B1}>
; CONDITION: #<ERROR {A9F68B1}>
NIL
That behaviour seems to be pretty much uniform on all
implementations. So it's probably me missing something rather some
implementation's quirk. (I'd expect only the "ERROR: ..." line to get
printed.)
Can anyone provide some insight?
-T.
From: Pascal Costanza
Subject: Re: Condition System; handlers simultaneously matching in the same binding form; CLHS 9.1.4
Date:
Message-ID: <6durujF4f2l7U2@mid.individual.net>
Tobias C. Rittweiler wrote:
> Hi,
>
> CLHS 9.1.4 states:
>
> Once a handler in a handler binding form (such as handler-bind or
> handler-case) has been selected, all handlers in that form become
> inactive for the remainder of the signaling process. While the
> selected handler runs, no other handler established by that form is
> active. That is, if the handler declines, __no other handler established
> by that form will be considered for possible invocation__.
>
> However, I don't understand the behaviour of the following snippet in
> light of the above paragraph:
>
> (handler-bind ((error #'(lambda (e) (format t "ERROR: ~S~%" e)))
> (condition #'(lambda (c) (format t "CONDITION: ~S~%" c))))
> (signal 'error))
>
> ; ERROR: #<ERROR {A9F68B1}>
> ; CONDITION: #<ERROR {A9F68B1}>
> NIL
>
> That behaviour seems to be pretty much uniform on all
> implementations. So it's probably me missing something rather some
> implementation's quirk. (I'd expect only the "ERROR: ..." line to get
> printed.)
>
> Can anyone provide some insight?
From the description of handler-bind: "If the handler declines, the
search continues for another handler."
From the glossary: "decline v. (of a handler) to return normally
without having handled the condition being signaled, permitting the
signaling process to continue as if the handler had not been present."
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Tobias C. Rittweiler
Subject: Re: Condition System; handlers simultaneously matching in the same binding form; CLHS 9.1.4
Date:
Message-ID: <878ww53dds.fsf@freebits.de>
Pascal Costanza <··@p-cos.net> writes:
> Tobias C. Rittweiler wrote:
>
> > CLHS 9.1.4 states:
> >
> > Once a handler in a handler binding form (such as handler-bind or
> > handler-case) has been selected, all handlers in that form become
> > inactive for the remainder of the signaling process. While the
> > selected handler runs, no other handler established by that form is
> > active. That is, if the handler declines, __no other handler established
> > by that form will be considered for possible invocation__.
>
> From the description of handler-bind: "If the handler declines, the
> search continues for another handler."
Right, the search is supposed to continue---further upwards, from my
reading stand point, at least.
-T.
From: Kent M Pitman
Subject: Re: Condition System; handlers simultaneously matching in the same binding form; CLHS 9.1.4
Date:
Message-ID: <u7ibppmhi.fsf@nhplace.com>
"Tobias C. Rittweiler" <···@freebits.de.invalid> writes:
> Pascal Costanza <··@p-cos.net> writes:
>
> > Tobias C. Rittweiler wrote:
> >
> > > CLHS 9.1.4 states:
> > >
> > > Once a handler in a handler binding form (such as handler-bind or
> > > handler-case) has been selected, all handlers in that form become
> > > inactive for the remainder of the signaling process. While the
> > > selected handler runs, no other handler established by that form is
> > > active. That is, if the handler declines, __no other handler established
> > > by that form will be considered for possible invocation__.
> >
> > From the description of handler-bind: "If the handler declines, the
> > search continues for another handler."
>
> Right, the search is supposed to continue---further upwards, from my
> reading stand point, at least.
FWIW, I agree with you and am pretty sure the intent of both the text and
the original sample implementation was exactly as you claim, notwithstanding
the fact that nearly everyone seems to do it the other way.
From http://www.nhplace.com/kent/CL/Revision-18.lisp.txt
here's the code:
(DEFUN SIGNAL (DATUM &REST ARGUMENTS)
(LET ((CONDITION (COERCE-TO-CONDITION DATUM ARGUMENTS
'SIMPLE-CONDITION 'SIGNAL))
(*HANDLER-CLUSTERS* *HANDLER-CLUSTERS*))
(IF (TYPEP CONDITION *BREAK-ON-SIGNALS*)
(BREAK "~A~%Break entered because of *BREAK-ON-SIGNALS*."
CONDITION))
(LOOP (IF (NOT *HANDLER-CLUSTERS*) (RETURN))
(LET ((CLUSTER (POP *HANDLER-CLUSTERS*)))
(DOLIST (HANDLER CLUSTER)
(WHEN (TYPEP CONDITION (CAR HANDLER))
(FUNCALL (CDR HANDLER) CONDITION)
(RETURN NIL) ;?
))))
NIL))
Note that a "cluster" is the datastructure corresponding the little group
of handlers you find in a handler-bind.
The "; ?" is from the actual text of that implementation and appears to
have indicated that this was a design question, since it could certainly
have been defined the other way.
I personally thought the implemented behavior to be the more useful, though
each is capable of implementing the other.
I do agree that the wording cited by Pascal creates a bit of confusion.
pc> From the description of handler-bind: "If the handler declines, the
pc> search continues for another handler."
pc>
pc> From the glossary: "decline v. (of a handler) to return normally
pc> without having handled the condition being signaled, permitting the
pc> signaling process to continue as if the handler had not been present."
Undoubtedly that confusion is my own doing, and I'm sorry about that.
But nevertheless, I think your response is the same one I'd have offered:
tcr> Right, the search is supposed to continue---further upwards, from my
tcr> reading stand point, at least.
I think a lot of the confusion arises because the notion in my head was
that it was also a design choice (which we inherited from the LispM) to even
do these typecase dispatches. Really it would have sufficed to do
(handler-bind just-one-handler &body forms)
and to make you do
(handler-bind #'(lambda (c)
(typecase c
...))
forms)
The design chooses to move the various cases outside the function on an
implicit theory that it will lead to more object-oriented design that way.
It means you can use individual named functions that are good at handling
this or that condition for exactly that condition and no other. But in
doing so, the question is whether these "clusters" are now a single handler
or many handlers. Clearly, the spec intends them as many handlers from a
terminology point of view, but they are still bundled.
To make them do the thing they do now is effectively to make things into
what I'd have wanted to call handler-bind*.
I'm not trying to advocate either the status quo or not, and my voice
at this point is just one of many in the community. But the above
information is offered just because I happened to have a few thoughts on
this that I figured I'd share. I hope it helps and doesn't just
muddy the waters.
From: Tobias C. Rittweiler
Subject: Re: Condition System; handlers simultaneously matching in the same binding form; CLHS 9.1.4
Date:
Message-ID: <8763r9seng.fsf@freebits.de>
Kent M Pitman <······@nhplace.com> writes:
> "Tobias C. Rittweiler" <···@freebits.de.invalid> writes:
>
> > Pascal Costanza <··@p-cos.net> writes:
> >
> > > Tobias C. Rittweiler wrote:
> > >
> > > > CLHS 9.1.4 states:
> > > >
> > > > Once a handler in a handler binding form (such as handler-bind or
> > > > handler-case) has been selected, all handlers in that form become
> > > > inactive for the remainder of the signaling process. While the
> > > > selected handler runs, no other handler established by that form is
> > > > active. That is, if the handler declines, __no other handler established
> > > > by that form will be considered for possible invocation__.
> > >
> > > From the description of handler-bind: "If the handler declines, the
> > > search continues for another handler."
> >
> > Right, the search is supposed to continue---further upwards, from my
> > reading stand point, at least.
>
> FWIW, I agree with you and am pretty sure the intent of both the text and
> the original sample implementation was exactly as you claim, notwithstanding
> the fact that nearly everyone seems to do it the other way.
I've been pointed out that the Examples section of SIGNAL looks like
(defun handle-division-conditions (condition)
(format t "Considering condition for division condition handling~%")
(when (and (typep condition 'arithmetic-error)
(eq '/ (arithmetic-error-operation condition)))
(invoke-debugger condition)))
(defun handle-other-arithmetic-errors (condition)
(format t "Considering condition for arithmetic condition handling~%")
(when (typep condition 'arithmetic-error)
(abort)))
(define-condition a-condition-with-no-handler (condition) ())
...
(handler-bind ((condition #'handle-division-conditions)
(condition #'handle-other-arithmetic-errors))
(signal 'a-condition-with-no-handler))
Considering condition for division condition handling
Considering condition for arithmetic condition handling
NIL
So this implementational mistake seems to date quite a bit into the
past. :-)
Thanks for your reply,
-T.
From: Pascal Costanza
Subject: Re: Condition System; handlers simultaneously matching in the same binding form; CLHS 9.1.4
Date:
Message-ID: <6dvb14F4ghodU1@mid.individual.net>
Tobias C. Rittweiler wrote:
> Pascal Costanza <··@p-cos.net> writes:
>
>> Tobias C. Rittweiler wrote:
>>
>>> CLHS 9.1.4 states:
>>>
>>> Once a handler in a handler binding form (such as handler-bind or
>>> handler-case) has been selected, all handlers in that form become
>>> inactive for the remainder of the signaling process. While the
>>> selected handler runs, no other handler established by that form is
>>> active. That is, if the handler declines, __no other handler established
>>> by that form will be considered for possible invocation__.
>> From the description of handler-bind: "If the handler declines, the
>> search continues for another handler."
>
> Right, the search is supposed to continue---further upwards, from my
> reading stand point, at least.
There seems to be a contradiction in the specification here.
The relevant section on handler-bind in its entirety:
"If more than one handler binding is supplied, the handler bindings are
searched sequentially from top to bottom in search of a match (by visual
analogy with typecase). If an appropriate type is found, the associated
handler is run in a dynamic environment where none of these handler
bindings are visible (to avoid recursive errors). If the handler
declines, the search continues for another handler.
If no appropriate handler is found, other handlers are sought from
dynamically enclosing contours. If no handler is found outside, then
signal returns or error enters the debugger."
The relevant formulation is "the search continues", which seems to
suggest to me that the "sequential search" mentioned in the first
sentence is referred to. The second paragraph talk about "no appropriate
handler is found", which seems to indicate that this happens after that
"sequential search" didn't find anything else.
The relevant section in 9.1.4 doesn't talk about handler-bind
specifically, but about "handler binding forms (such as handler-bind or
handler-case)" in general.
It seems to me that this is a case where 1.5.1.4.1 applies.
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Tobias C. Rittweiler
Subject: Re: Condition System; handlers simultaneously matching in the same binding form; CLHS 9.1.4
Date:
Message-ID: <871w1xsbb2.fsf@freebits.de>
Pascal Costanza <··@p-cos.net> writes:
> There seems to be a contradiction in the specification here.
>
> The relevant section on handler-bind in its entirety:
>
> "If more than one handler binding is supplied, the handler bindings
> are searched sequentially from top to bottom in search of a match (by
> visual analogy with typecase). If an appropriate type is found, the
> associated handler is run in a dynamic environment where none of these
> handler bindings are visible (to avoid recursive errors). If the
> handler declines, the search continues for another handler.
>
> If no appropriate handler is found, other handlers are sought from
> dynamically enclosing contours. If no handler is found outside, then
> signal returns or error enters the debugger."
>
> The relevant formulation is "the search continues", which seems to
> suggest to me that the "sequential search" mentioned in the first
> sentence is referred to. The second paragraph talk about "no
> appropriate handler is found", which seems to indicate that this
> happens after that "sequential search" didn't find anything else.
Not necessarily. The second paragraph talks about the case where _no_
matching handler could be found within the current HANDLER-BIND form,
whereas the last sentence of the first paragraph talks about the case
where a matching handler was found. So the two paragraphs don't have
much to do with each other, as they describe two different cases.
(In fact, it could be argued that identical behaviour for both cases is
more reasonable, which would be an argument for 9.1.4 taking place.)
But I agree that the section can be interpreted either way. Hence my
posting in the first place.
-T.