Let me quote HyperSpec
'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.'
Seemed to me this concerns one handler-bind form. What should take place when
I have several of them nested? For example:
(handler-bind ((specific-condition-2 #'(lambda (c) (print "specific"))))
(handler-bind ((general-condition-2 #'(lambda (c) (print "general"))))
(signal 'specific-condition-2)))
--
Vladimir Zolotykh
In article <·················@eurocom.od.ua>,
Vladimir Zolotykh <······@eurocom.od.ua> wrote:
>Let me quote HyperSpec
>
>'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.'
>
>Seemed to me this concerns one handler-bind form. What should take place when
>I have several of them nested? For example:
The most recently established handler that matches the condition will be
invoked.
>(handler-bind ((specific-condition-2 #'(lambda (c) (print "specific"))))
> (handler-bind ((general-condition-2 #'(lambda (c) (print "general"))))
> (signal 'specific-condition-2)))
This will print "general".
--
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
Barry Margolin <······@genuity.net> writes:
> In article <·················@eurocom.od.ua>,
> Vladimir Zolotykh <······@eurocom.od.ua> wrote:
> >Let me quote HyperSpec
> >
> >'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.'
> >
> >Seemed to me this concerns one handler-bind form. What should take place when
> >I have several of them nested? For example:
>
> The most recently established handler that matches the condition will be
> invoked.
>
> >(handler-bind ((specific-condition-2 #'(lambda (c) (print "specific"))))
> > (handler-bind ((general-condition-2 #'(lambda (c) (print "general"))))
> > (signal 'specific-condition-2)))
>
> This will print "general".
I agree with Barry (assuming as he does that a specific-condition-2 is also
of type general-condition-2.
However, I'm curious: what did you expect and why? Do you think the
behavior Barry suggests is wrong, and if so, why?
Kent M Pitman wrote:
>
> Barry Margolin <······@genuity.net> writes:
>
> > In article <·················@eurocom.od.ua>,
> > Vladimir Zolotykh <······@eurocom.od.ua> wrote:
> > >Let me quote HyperSpec
> > >
> > >'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.'
> > >
> > >Seemed to me this concerns one handler-bind form. What should take place when
> > >I have several of them nested? For example:
> >
> > The most recently established handler that matches the condition will be
> > invoked.
> >
> > >(handler-bind ((specific-condition-2 #'(lambda (c) (print "specific"))))
> > > (handler-bind ((general-condition-2 #'(lambda (c) (print "general"))))
> > > (signal 'specific-condition-2)))
> >
> > This will print "general".
>
> I agree with Barry (assuming as he does that a specific-condition-2 is also
> of type general-condition-2.
Sorry for forgetting that, of course
(define-condition general-condition-2 () ())
(define-condition specific-condition-2 (general-condition-2) ())
>
> However, I'm curious: what did you expect and why? Do you think the
> behavior Barry suggests is wrong, and if so, why?
Knowing CLOS a little I might guessed the more specific handler could be
considered first. This is not. Reading HyperSpec I had supposed the visual
order governs all. This is also not. The nearest (dynamically) handler take
precedence over most specific and in one handler-bind visual order determines
all (among applicable handlers of course). I just had wanted to make sure
I understand things right.
--
Vladimir Zolotykh
Vladimir Zolotykh <······@eurocom.od.ua> writes:
> Knowing CLOS a little I might guessed the more specific handler could be
> considered first. This is not. Reading HyperSpec I had supposed the visual
> order governs all. This is also not. The nearest (dynamically) handler take
> precedence over most specific and in one handler-bind visual order determines
> all (among applicable handlers of course). I just had wanted to make sure
> I understand things right.
It is important to understand that this is a dynamic issue that intentionally
involves search.
Consider what would happen if you wrote:
(defun reciprocal-or-nil (x) (ignore-errors (/ 1 x)))
There would be no way you could, in a modular way, prove the correctness
of this function if some containing routine could do:
(defun one (seed)
(handler-case (let ((recip (reciprocal-or-nil seed)))
(if recip
(* recip seed)
;; otherwise,
;; if we couldn't find reciprocal,
;; just return a symbolic result
'one))
(arithmetic-error 'unknown)))
(one 3) => 1
(one 3.0) => 1.0
(one nil) => ONE
(one 0) => ONE
But if the "more specific" function could trap something on an inner
computation that was handled within that computation, you couldn't test
the inner computation in isolation, and you'd get
(one 0) => UNKNOWN
even though
(reciprocal-or-nil 0) => NIL
in earlier tests.
The design of the condition system is intended to yield reliable,
modular behavior in dynamically composed call chains.
Kent M Pitman wrote:
>
[snip]
> But if the "more specific" function could trap something on an inner
> computation that was handled within that computation, you couldn't test
> the inner computation in isolation, and you'd get
>
> (one 0) => UNKNOWN
>
> even though
>
> (reciprocal-or-nil 0) => NIL
Thank you Kent for excellent example. It clearly settled the matter.
--
Vladimir Zolotykh
Vladimir Zolotykh <······@eurocom.od.ua> writes:
> Kent M Pitman wrote:
> >
> [snip]
>
> > But if the "more specific" function could trap something on an inner
> > computation that was handled within that computation, you couldn't test
> > the inner computation in isolation, and you'd get
> >
> > (one 0) => UNKNOWN
> >
> > even though
> >
> > (reciprocal-or-nil 0) => NIL
>
> Thank you Kent for excellent example. It clearly settled the matter.
No problem. I hope you find the utility function useful as well.
It's often very useful to be able to compute that particular constant. ;)
"Barry Margolin" <······@genuity.net> wrote in message
····················@paloalto-snr2.gtei.net...
> In article <·················@eurocom.od.ua>,
> Vladimir Zolotykh <······@eurocom.od.ua> wrote:
> >Let me quote HyperSpec
> >
> >'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.'
> >
> >Seemed to me this concerns one handler-bind form. What should take place when
> >I have several of them nested? For example:
>
> The most recently established handler that matches the condition will be
> invoked.
>
> >(handler-bind ((specific-condition-2 #'(lambda (c) (print "specific"))))
> > (handler-bind ((general-condition-2 #'(lambda (c) (print "general"))))
> > (signal 'specific-condition-2)))
>
> This will print "general".
Or, to be precise, it will print "general" and "specific" and then return nil
because all of the handlers decline.
--
Martin Simmons
······@xanalys.com
rot13 to reply
"Martin Simmons" <······@xanalys.com> writes:
> > >(handler-bind ((specific-condition-2 #'(lambda (c) (print "specific"))))
> > > (handler-bind ((general-condition-2 #'(lambda (c) (print "general"))))
> > > (signal 'specific-condition-2)))
> >
> > This will print "general".
>
> Or, to be precise, it will print "general" and "specific" and then return nil
> because all of the handlers decline.
Heh. Good (non)catch.