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.