From: Keke Abe
Subject: handler-bind
Date: 
Message-ID: <keke-1105011839430001@solg4.keke.org>
I'm wondering whether the second handler of the following 
handler-bind form should be called or not.

(catch 'abort
  (handler-bind ((error #'(lambda (c)
                            (declare (ignore c))
                            (princ "Handler #1")))
                 (error #'(lambda (c)
                            (declare (ignore c))
                            (princ "Handler #2")
                            (throw 'abort nil))))
    (error "testing handler-bind")))


The HyperSpec [9.1.4 Signaling and Handling Conditions] says:

    [...]
    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.

It looks like suggesting that the second handler of the above won't 
be invoked. However, the following [again from HyperSpec on 
HANDLER-BIND]:

    [...]
    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.

sounds like indicating that the second handler should be called. 
Where have I lost?

Thanks for your help.
Takehiko Abe

--
"If this were a dictatorship, it'd be a heck of a lot easier,
 just so long as I'm the dictator."          
                                             - George W Bush

From: Kent M Pitman
Subject: Re: handler-bind
Date: 
Message-ID: <sfwheysxl55.fsf@world.std.com>
····@mac.com (Keke Abe) writes:

> 
> I'm wondering whether the second handler of the following 
> handler-bind form should be called or not.
> 
> (catch 'abort
>   (handler-bind ((error #'(lambda (c)
>                             (declare (ignore c))
>                             (princ "Handler #1")))
>                  (error #'(lambda (c)
>                             (declare (ignore c))
>                             (princ "Handler #2")
>                             (throw 'abort nil))))
>     (error "testing handler-bind")))
> 
> 
> The HyperSpec [9.1.4 Signaling and Handling Conditions] says:
> 
>     [...]
>     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.
> 
> It looks like suggesting that the second handler of the above won't 
> be invoked. However, the following [again from HyperSpec on 
> HANDLER-BIND]:
> 
>     [...]
>     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.
> 
> sounds like indicating that the second handler should be called. 
> Where have I lost?

I think it means the search continues outward for other, 
dynamically-enclosing clusters of handler-bindings.

The intent of allowing HANDLER-BIND more than one binding is to allow you
to provide specific handlers for a specific circumstance, but the handler
bindings in any given HANDLER-BIND are intended to deal with a unitary 
understanding of a situation.  

Using nested HANDLER-BINDs will do what looks like the right thing for you.
From: Keke Abe
Subject: Re: handler-bind
Date: 
Message-ID: <keke-1105012231070001@solg4.keke.org>
In article <···············@world.std.com>,
Kent M Pitman wrote:

> I think it means the search continues outward for other, 
> dynamically-enclosing clusters of handler-bindings.
> 
> The intent of allowing HANDLER-BIND more than one binding is to allow you
> to provide specific handlers for a specific circumstance, but the handler
> bindings in any given HANDLER-BIND are intended to deal with a unitary 
> understanding of a situation.  
> 

Thank you. I came to this question last October and thought that it might
be a bug of MCL (the implementation I use). I even posted the same question
to the MCL mailing list but didn't get much response then. I should have
asked this earlier here in comp.lang.lisp so that I could get the answer
from you.

Now that I've got a definitive answer [I am fully aware that you are not
the HyperSpec nor the ANSI CL Spec], I think I should post to the MCL
mailing again. Could I quote you in it?

regards,
Takehiko Abe
--
[silly sig deleted]
From: Kent M Pitman
Subject: Re: handler-bind
Date: 
Message-ID: <sfwzocivfod.fsf@world.std.com>
····@mac.com (Keke Abe) writes:

> In article <···············@world.std.com>, Kent M Pitman wrote:
> 
> > I think it means the search continues outward for other, 
> > dynamically-enclosing clusters of handler-bindings.
> > 
> > The intent of allowing HANDLER-BIND more than one binding is to allow you
> > to provide specific handlers for a specific circumstance, but the handler
> > bindings in any given HANDLER-BIND are intended to deal with a unitary 
> > understanding of a situation.  
> 
> Thank you. I came to this question last October and thought that it might
> be a bug of MCL (the implementation I use). I even posted the same question
> to the MCL mailing list but didn't get much response then. I should have
> asked this earlier here in comp.lang.lisp so that I could get the answer
> from you.
> 
> Now that I've got a definitive answer [I am fully aware that you are not
> the HyperSpec nor the ANSI CL Spec], I think I should post to the MCL
> mailing again. Could I quote you in it?

Sorry to take so long to get back to you on this; I got delayed by some
research on the topic I tried to do.

You can quote me as having said what I said, but let me add that the one
thing I *really* wanted to do was to go back to the sample implementation
I had distributed.  I've been poking around in my online files and fear it's
also among the things that's presently offline (in backups).  I think I've
distributed copies to others around the net, though, so if anyone has a copy
of the Revision 18 sample implementation and they could send me a pointer,
that'd be handy.  I'd consider that implementation, because it was 
incorporated by a number of vendors, to be more definitive.

The truth is, though, that any legitimate interpretation of the
wording is valid and conforming.  It is not the place of any one
person or organization to dictate what is right.

I looked back at the original proposal to ANSI (which was incorporated
into the draft standard and subsequently modified in various ways, but
not, I believe, on this point) and it has pretty much the same wording.

  If more than one binding is specified, the 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 context where none of the BINDINGS are visible (to avoid
  recursive errors). For example, in the case of:
	(HANDLER-BIND ((UNBOUND-VARIABLE #'(LAMBDA ...))
		       (ERROR #'(LAMBDA ...)))
	  ...)
  if an unbound variable error is signalled in the body (and not handled
  by an intervening handler), the first function will be called. If any
  other kind of error is signalled, the second function will be called.
  In either case, neither handler will be active while executing the code
  in the associated function.

Btw, LispWorks 4.1.20 disagrees with me, at least in implementation, not
sure about intent.  It does:

 (handler-bind ((error #'(lambda (c) (break "Bar: ~A" c))))
   (handler-bind ((error #'(lambda (c) nil))
                  (error #'(lambda (c) (break "Foo: ~A" c))))
     (error "Testing...")))

 Foo: Testing...

where I would have expected to break with "Bar: Testing...".

Both interpretations seem "reasonable" and I don't know what to say is
right.  But my impression is that it's more debuggable if you think of
each handler-bind as a typecase (which would mean only one item gets done)
and the search as a process of trying each of those typecases.  But
I can imagine someone thinking otherwise.

The one thing that leans the argument just a little bit in favor of the
"MCL" interpretation is the remark that the handlers available in the
selected clause don't see the other handlers in the other clauses.
Normally, there is a "firewall" built that keeps the "unwound" things from
being seen but leaves the "wound" things visible as handlers are tried.
Since the sibling clauses are not visible, that gives the strongest claim
to the idea that they should also be treated as "already unwound" and so
not searched if search resumes.   This is an obscure point that might have
gone past some implementors, but I would consider it to be "necessary 
consistency".  The only problem is that others probably wouldn't, and my
opinion's no more valuable than anyone else's, even if I did write that part
of the spec and the sample implementation.  Once we voted on the standard,
only the actual words of the standard matter, and the rest of this is just
the moral equivalent of the Jerry Springer show, adapted for a parenthetically inclined audience.

So my feeling is now firmly for that MCL position is the best one for
internal consistency of the language, but that both the MCL and LW positions
are at least superficially defensible.
From: Pierre R. Mai
Subject: Re: handler-bind
Date: 
Message-ID: <87itj6fwf1.fsf@orion.bln.pmsf.de>
Kent M Pitman <······@world.std.com> writes:

> I looked back at the original proposal to ANSI (which was incorporated
> into the draft standard and subsequently modified in various ways, but
> not, I believe, on this point) and it has pretty much the same wording.
> 
>   If more than one binding is specified, the 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 context where none of the BINDINGS are visible (to avoid
>   recursive errors). For example, in the case of:
> 	(HANDLER-BIND ((UNBOUND-VARIABLE #'(LAMBDA ...))
> 		       (ERROR #'(LAMBDA ...)))
> 	  ...)
>   if an unbound variable error is signalled in the body (and not handled
>   by an intervening handler), the first function will be called. If any
>   other kind of error is signalled, the second function will be called.
>   In either case, neither handler will be active while executing the code
>   in the associated function.
> 
> Btw, LispWorks 4.1.20 disagrees with me, at least in implementation, not
> sure about intent.  It does:
> 
>  (handler-bind ((error #'(lambda (c) (break "Bar: ~A" c))))
>    (handler-bind ((error #'(lambda (c) nil))
>                   (error #'(lambda (c) (break "Foo: ~A" c))))
>      (error "Testing...")))
> 
>  Foo: Testing...
> 
> where I would have expected to break with "Bar: Testing...".

Both ACL and CMU CL seem to agree with LispWorks on that point, both
first breaking into the Foo: Testing break-loop, instead of proceeding
directly into the Bar: Testing break-loop...

CLISP seems to agree with the MCL interpretation.

FWIW the CMU CL conditions implementation seems to be based on your
prototypical implementation, though it is really unclear which version
of that implementation that was, and whether later changes have any
bearing on that aspect.  From the source:

;;;
;;; This is a condition system for CMU Common Lisp.
;;; It was originally taken from some prototyping code written by ···@Symbolics
;;; and massaged for our uses.
;;;

> So my feeling is now firmly for that MCL position is the best one for
> internal consistency of the language, but that both the MCL and LW positions
> are at least superficially defensible.

Indeed I would have expected the MCL position to be more wide-spread
than it is.

Regs, Pierre.

-- 
Pierre R. Mai <····@acm.org>                    http://www.pmsf.de/pmai/
 The most likely way for the world to be destroyed, most experts agree,
 is by accident. That's where we come in; we're computer professionals.
 We cause accidents.                           -- Nathaniel Borenstein
From: Kent M Pitman
Subject: Re: handler-bind
Date: 
Message-ID: <sfw7kzm5tkw.fsf@world.std.com>
"Pierre R. Mai" <····@acm.org> writes:

> Kent M Pitman <······@world.std.com> writes:
> [...] 
> Indeed I would have expected the MCL position to be more wide-spread
> than it is.

I'm sure if we dig far enough we'll find that the divergence is due to
me forgetting the original intent and sending some bug report arguing
it should be changed, and then them believing me more than they should 
have. 
 --Kent (only half-joking -- sigh)
From: Erik Naggum
Subject: Re: handler-bind
Date: 
Message-ID: <3198759540763430@naggum.net>
* Kent M Pitman
> Btw, LispWorks 4.1.20 disagrees with me, at least in implementation, not
> sure about intent.  It does:
> 
>  (handler-bind ((error #'(lambda (c) (break "Bar: ~A" c))))
>    (handler-bind ((error #'(lambda (c) nil))
>                   (error #'(lambda (c) (break "Foo: ~A" c))))
>      (error "Testing...")))
> 
>  Foo: Testing...
> 
> where I would have expected to break with "Bar: Testing...".

* "Pierre R. Mai" <····@acm.org>
> Both ACL and CMU CL seem to agree with LispWorks on that point, both
> first breaking into the Foo: Testing break-loop, instead of proceeding
> directly into the Bar: Testing break-loop...

  I remain uncertain what we are demonstrating here, but for what it might
  be worth, Allegro CL 6.0 breaks with "Bar: More Testing..." when running
  this snippet of code:

(handler-bind ((error #'(lambda (c) (break "Bar: ~A" c))))
  (handler-bind ((error #'(lambda (c) (error "More ~A" c)))
		 (error #'(lambda (c) (break "Foo: ~A" c))))
    (error "Testing...")))

  while breaking with "Foo: Testing..." in the example quoted above, which
  does indicate that the next handler is not visible while in the handler,
  but somehow reinstated when searching for an applicable handler, like
  cond instead of like typecase.

#:Erik
-- 
  Travel is a meat thing.
From: Keke Abe
Subject: Re: handler-bind
Date: 
Message-ID: <keke-1305012224100001@solg4.keke.org>
In article <···············@world.std.com>, Kent M Pitman <······@world.std.com> wrote:

> [...]
> The truth is, though, that any legitimate interpretation of the
> wording is valid and conforming.  It is not the place of any one
> person or organization to dictate what is right.

I suppose this flexibility is good. Dogmatic interpretation of the
script --literalism leads to all the evil. Yet I think knowing the
original intent [as recalled or recorded] is valuable.

> I looked back at the original proposal to ANSI (which was incorporated
> into the draft standard and subsequently modified in various ways, but
> not, I believe, on this point) and it has pretty much the same wording.
> 
>   If more than one binding is specified, the 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 context where none of the BINDINGS are visible (to avoid
>   recursive errors). For example, in the case of:
>         (HANDLER-BIND ((UNBOUND-VARIABLE #'(LAMBDA ...))
>                        (ERROR #'(LAMBDA ...)))
>           ...)
>   if an unbound variable error is signalled in the body (and not handled
>   by an intervening handler), the first function will be called. If any
>   other kind of error is signalled, the second function will be called.
>   In either case, neither handler will be active while executing the code
>   in the associated function.

I looked into the TeX source of ANSI Draft, and the part of the HANDLER-BIND
dictionary contains the following comment:

  %!!! Barmar: The next two paragraphs belong in description of signaling,
  %      not handling. [I agree. -kmp]
  If more than one \param{handler} \term{binding} is supplied, [...]

I'm not sure what the comment means. Also, for 9.1.4 Signaling and Handling
Conditions, there is:

  %!!! Barrett:  This doesn't match my reading of CSv18, p12.
  %     I believe contradicts p21,p22 of that document.  It also differs from
  %     previous paragraph (w/ item 2) and first paragraph under "signaling".
  Once a handler in a handler binding \term{form} (such as 
  \macref{handler-bind} or \macref{handler-case}) has been selected, all
  handlers in that \term{form} become inactive for 
  the remainder of the signaling process.
  %--------------------------------------
  While the selected \term{handler} runs, no other \term{handler} established
  by that \term{form} is active. That is, if the \term{handler} declines, 
  no other handler established by that \term{form} will be considered for
  possible invocation.
  %-------------------------------------------------------------------------

The "previous paragraph":

  2. Let h1 and h2 be two applicable active handlers established by the same
  form. Then h1 is more recent than h2 if h1 was defined to the left of h2 in
  the form that established them. 


The "first paragraph under \"signaling\"":

  9.1.4.1 Signaling

  When a condition is signaled, the most recent applicable active handler is
  invoked. Sometimes a handler will decline by simply returning without a
  transfer of control. In such cases, the next most recent applicable active
  handler is invoked. 

Again, I'm not sure what contradicts what. I don't know what CSv18 is.
Maybe that's the sample implementation you're looking for?

[btw, I didn't know that the TeX source of ANSI drafts contains all those
 very interesting comments until Kim Barret mentioned to it in MCL mailing
 a while back. I found them valuable reading as a supplement to the
 HyperSpec.... Just for those who don't know yet that they're available.
 btw2, I regarded the HyperSpec as a reference material at first but then
 found it make a very good reading material and imo its organization an
 improvement from that of CLtL2. I want a handbook version.]


> Btw, LispWorks 4.1.20 disagrees with me, at least in implementation, not
> sure about intent.  It does:
> 
>  (handler-bind ((error #'(lambda (c) (break "Bar: ~A" c))))
>    (handler-bind ((error #'(lambda (c) nil))
>                   (error #'(lambda (c) (break "Foo: ~A" c))))
>      (error "Testing...")))
> 
>  Foo: Testing...
> 
> where I would have expected to break with "Bar: Testing...".
> 
> Both interpretations seem "reasonable" and I don't know what to say is
> right.  But my impression is that it's more debuggable if you think of
> each handler-bind as a typecase (which would mean only one item gets done)
> and the search as a process of trying each of those typecases.  But
> I can imagine someone thinking otherwise.

I came to the question originally while I was reading the HyperSpec and
learning the Condition system [still learning] and trying some possible
use of its functions. I thought I could make one handler a default method
for a set of conditions and do some common handling there:

(define-condition condition-a () ...)
(define-condition condition-a-1 (condition-a) ...)
...
(handler-bind ((condition-a #'(lambda (c) .....))
               (condition-a-1 #'(lambda (c) ...))
               (condition-a-2 #'(lambda (c) ...)))
  ....)

So I was learning/experimenting, and this isn't what I _really_ need.
I'm not sure this makes debugging tasks harder. I must admit that I
am a kind of person who can't grasp what makes a bad coding style
til I am hit hard.

> 
> The one thing that leans the argument just a little bit in favor of the
> "MCL" interpretation is the remark that the handlers available in the
> selected clause don't see the other handlers in the other clauses.
> Normally, there is a "firewall" built that keeps the "unwound" things from
> being seen but leaves the "wound" things visible as handlers are tried.
> Since the sibling clauses are not visible, that gives the strongest claim
> to the idea that they should also be treated as "already unwound" and so
> not searched if search resumes.   This is an obscure point that might have
> gone past some implementors, but I would consider it to be "necessary 
> consistency". The only problem is that others probably wouldn't, and my
> opinion's no more valuable than anyone else's, even if I did write that part
> of the spec and the sample implementation.  Once we voted on the standard,
> only the actual words of the standard matter, and the rest of this is just
> the moral equivalent of the Jerry Springer show, adapted for a parenthetically
> inclined audience.

I don't know what the Jerry Springer show is or how good it is, but I
think the information you provided here for us is very valuable. Thank
you.

regards,
Takehiko Abe
From: Kent M Pitman
Subject: Re: handler-bind
Date: 
Message-ID: <sfw1yptp8uq.fsf@world.std.com>
····@mac.com (Keke Abe) writes:

> Again, I'm not sure what contradicts what. I don't know what CSv18 is.
> Maybe that's the sample implementation you're looking for?

No, but there were two joined documents.

 Condition System, Revision 18
 [ http://world.std.com/~pitman/Papers/Revision-18.txt

and an accompanying sample implementation that purported to implement
this particular revision.

> [btw, I didn't know that the TeX source of ANSI drafts contains all those
>  very interesting comments until Kim Barret mentioned to it in MCL mailing
>  a while back. I found them valuable reading as a supplement to the
>  HyperSpec.... Just for those who don't know yet that they're available.
>  btw2, I regarded the HyperSpec as a reference material at first but then
>  found it make a very good reading material and imo its organization an
>  improvement from that of CLtL2. I want a handbook version.]

Well, the problem is that the TeX source contains contradictory and
out-of-date comment information that would be confusing, so I haven't
in general cited it.  But certainly we do from time to time go back to it
to see if it offers "clues".

CLTL2 is different in other than just organization.  It contains
factually different information, not authorized for release by the
committee.  I suppose in that sense, so does the TeX source of the
spec.  Into the TeX source of the ANSI CL document, I just dumped lots
of stuff into comments when I didn't have any other place for it, so
it's got a lot of archeological interest, but perhaps less formal
interest.  But back to CLTL to make another point that I haven't had a
chance to make in a while: CLTL1 was a committee product, approved and
reviewed by a committee.  CLTL2 was a private effort by Steele, not
authorized by the committee, that took a snapshot of work in progress,
some of which we backed out of before the end.  Further CLTL2 was
presented in a style that emphasized diffs, more than truth, and so
made it very hard to read because it's always saying "x is true.  no
wait, it isn't any more. we changed that."  To some degree, the TeX
comments occasionally share this sense, too.

And the TeX sourcs are a pretty tedious read.

[Also, btw, just to be 100% literal about this, you don't have the TeX source
of ANSI CL itself.  What you have differs only in cosmetic ways, and in no
technical way, but for copyright reasons there is a minor difference.  Not
to mention a difference in about 200 pages (1150 pages in ANSI CL instead
of 1350 in the draft you can make from the publicly available sources) that
I got by "book design" (font choice and squeezing out vertical whitespace)
for final publication!]

> > ... Once we voted on the standard, only the actual words of the
> > standard matter, and the rest of this is just the moral equivalent
> > of the Jerry Springer show, adapted for a parenthetically inclined
> > audience.
>
> I don't know what the Jerry Springer show is or how good it is,

(It's extraordinarily popular with the mainstream public of the US,
consisting mostly of invited guests on outlandish topics saying rude
things to each other until they get mad enough that they try to beat
each other up and have to be stopped by big burly guys hired by the
show to keep the guests from killing each other.)

> but I think the information you provided here for us is very valuable.
> Thank you.

Happy to help.  I'm sure I'll find the sample implementation at some point,
and at that point I'll post the additional clue it will provide.