From: Christian Lynbech
Subject: coding style question: handler-case usage
Date: 
Message-ID: <ofg08su161.fsf@chl.ted.dk.eu.ericsson.se>
I recently discovered that our application is filled to the brim
(well, allmost :-) with `handler-case' forms.

My own gut feeling is that `handler-case' is a "special purpose" form,
ie. that it is used in a few distinct corners of an application,
rather than all over the place. Certainly, many of the instances could
might as well have been written using `unwind-protect'.

So I would appreciate some senior advice on what to think of this.

I will try to phrase some more specific questions below, but let me
first explain a bit about what we are trying to do. Our application
acts as an agent to the outside (for SNMP) and kind of translates
requests in the standard protocol into requests in a proprietary lower
layer protocol towards a set of modules doing the actual routing and
payload trafficking. The agent must be robust (and basically is a
non-interactive application) so fault tolerance is essential.

My questions revolve around issues such as:

   - is `unwind-protect' less "heavy" than `handler-case' (ie. should
     we use that when what are doing is just cleaning up)

   - is it better to use `unwind-protect' and `handler-case' directly,
     or should we devise new syntax since the cases are numerous (I
     know, quite impossible to answer in general)

   - is it wrong of us to use the condition system to propagate
     exceptions (an example of the need for error handling comes from
     the fact that when a low level request fails, we signal an error,
     rather than just returning some kind of error object)


------------------------+-----------------------------------------------------
Christian Lynbech       | Ericsson Telebit, Skanderborgvej 232, DK-8260 Viby J
Phone: +45 8938 5244    | email: ·················@ted.ericsson.dk
Fax:   +45 8938 5101    | web:   www.ericsson.com
------------------------+-----------------------------------------------------
Hit the philistines three times over the head with the Elisp reference manual.
                                        - ·······@hal.com (Michael A. Petonic)

From: ···@itasoftware.com
Subject: Re: coding style question: handler-case usage
Date: 
Message-ID: <r8sc1w05.fsf@itasoftware.com>
Christian Lynbech <·················@ted.ericsson.dk> writes:

> I recently discovered that our application is filled to the brim
> (well, allmost :-) with `handler-case' forms.
> 
> My own gut feeling is that `handler-case' is a "special purpose" form,
> ie. that it is used in a few distinct corners of an application,
> rather than all over the place. Certainly, many of the instances could
> might as well have been written using `unwind-protect'.
> 
> So I would appreciate some senior advice on what to think of this.
> 
> I will try to phrase some more specific questions below, but let me
> first explain a bit about what we are trying to do. Our application
> acts as an agent to the outside (for SNMP) and kind of translates
> requests in the standard protocol into requests in a proprietary lower
> layer protocol towards a set of modules doing the actual routing and
> payload trafficking. The agent must be robust (and basically is a
> non-interactive application) so fault tolerance is essential.
> 
> My questions revolve around issues such as:
> 
>    - is `unwind-protect' less "heavy" than `handler-case' (ie. should
>      we use that when what are doing is just cleaning up)

Handler-case, handler-bind, and unwind-protect are generally
implemented by pushing a special marker on the stack and possibly
binding some special variables.  I doubt that there would be much
performance difference between the three in non-signalling code.

In the case of handling a signal, there is a search for the handler
and that may make a slight difference.

>    - is it better to use `unwind-protect' and `handler-case' directly,
>      or should we devise new syntax since the cases are numerous (I
>      know, quite impossible to answer in general)

Would it abstract away certain complexity?  If you had some `idiom'
that was repeatedly used it would probably be reasonable to wrap it
somehow.  (But try not to invent brand new syntax, a WITH-MUMBLE-FROTZ
macro ought to be adequate.)

>    - is it wrong of us to use the condition system to propagate
>      exceptions (an example of the need for error handling comes from
>      the fact that when a low level request fails, we signal an error,
>      rather than just returning some kind of error object)

The reason there is a condition system is that returning error objects
sucks.
From: Barry Margolin
Subject: Re: coding style question: handler-case usage
Date: 
Message-ID: <G5Iw7.21$vN6.1098@burlma1-snr2>
In article <··············@chl.ted.dk.eu.ericsson.se>,
Christian Lynbech  <·················@ted.ericsson.dk> wrote:
>
>I recently discovered that our application is filled to the brim
>(well, allmost :-) with `handler-case' forms.
>
>My own gut feeling is that `handler-case' is a "special purpose" form,
>ie. that it is used in a few distinct corners of an application,
>rather than all over the place. Certainly, many of the instances could
>might as well have been written using `unwind-protect'.

It seems strange to me that you lump these two together.  HANDLER-CASE is
much more related to CATCH than it is to UNWIND-PROTECT.

>My questions revolve around issues such as:
>
>   - is `unwind-protect' less "heavy" than `handler-case' (ie. should
>     we use that when what are doing is just cleaning up)

The general expectation is that conditions are signalled in unusual
situations.  So something that's part of the normal cleanup process when
exiting a form should probably be done using UNWIND-PROTECT rather than
HANDLER-BIND.

HANDLER-BIND is likely to have more overhead than UNWIND-PROTECT, because
it has to match conditions against a hierarchy of condition types.  Since
conditions are usually only signalled for exceptions, the overhead is not
usually considered significant.  I would be wary of coding an application
in such a way that condition signalling is common in an inner loop.

>   - is it better to use `unwind-protect' and `handler-case' directly,
>     or should we devise new syntax since the cases are numerous (I
>     know, quite impossible to answer in general)

If there's a common pattern to your use of them, it's often a good idea to
encapsulate that into a macro.  The name of the macro provides a useful
abstraction, and the use of the macro helps avoid errors.

>   - is it wrong of us to use the condition system to propagate
>     exceptions (an example of the need for error handling comes from
>     the fact that when a low level request fails, we signal an error,
>     rather than just returning some kind of error object)

This is precisely what the condition system is intended to be used for.

-- 
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.
From: Kent M Pitman
Subject: Re: coding style question: handler-case usage
Date: 
Message-ID: <sfwzo701rwr.fsf@world.std.com>
Barry Margolin <······@genuity.net> writes:

> In article <··············@chl.ted.dk.eu.ericsson.se>,
> Christian Lynbech  <·················@ted.ericsson.dk> wrote:
> >
> >I recently discovered that our application is filled to the brim
> >(well, allmost :-) with `handler-case' forms.
> >
> >My own gut feeling is that `handler-case' is a "special purpose" form,
> >ie. that it is used in a few distinct corners of an application,
> >rather than all over the place. Certainly, many of the instances could
> >might as well have been written using `unwind-protect'.
> 
> It seems strange to me that you lump these two together.  HANDLER-CASE is
> much more related to CATCH than it is to UNWIND-PROTECT.

I agree.

In addition to Barry's point here, which I would re-express as
"HANDLER-CASE arranges for a transfer of control in the event of an error"
while "UNWIND-PROTECT arranges for a passive detour in control but 
really is neither transferring nor receiving control in the same sense".
These are just apples and oranges and are not possible to interchange.

*** A code sample here would help a lot, I think. ***

Moreover, HANDLER-CASE involves discretionary actions (to be done only if
a given condition is signaled and it not trapped by some other handler, 
whereas UNWIND-PROTECT involves unconditional actions.  Among the 
considerations in selecting which to use, if not both, is the issue of 
whether something must always or only sometimes happen.

> >My questions revolve around issues such as:
> >
> >   - is `unwind-protect' less "heavy" than `handler-case' (ie. should
> >     we use that when what are doing is just cleaning up)
> 
> The general expectation is that conditions are signalled in unusual
> situations.  So something that's part of the normal cleanup process when
> exiting a form should probably be done using UNWIND-PROTECT rather than
> HANDLER-BIND.

My paper http:/world.std.com/pitman/Papers/Exceptional-Situations-1990.html
is probably something worth reading in order to get some of the philosophy
behind the condition chapter in CLHS.  I *assume* Christian has at least
read the CLHS conditions chapter fully, but if not he should do that as
well.
 
> HANDLER-BIND is likely to have more overhead than UNWIND-PROTECT, because
> it has to match conditions against a hierarchy of condition types.  Since
> conditions are usually only signalled for exceptions, the overhead is not
> usually considered significant.  I would be wary of coding an application
> in such a way that condition signalling is common in an inner loop.

I usually say it this way:  the condition system is an introspective protocol.
The thing about introspective protocols is that they are two halves of
a communication with enough inquiry capability to be able to ask what the
other half is doing.  But when you control both halves of the code, that's
often unnecessary overhead because you can just know what the other half is
doing.  (Sometimes for modularity reasons you may write a boundary "as if"
it might be broken up later, but that's a different thing.  Every function
call boundary is not a true module boundary, even though the boundary is
subjectively drawn and might be different for different situations.)

My conditions paper above addresses some of these issues.

> >   - is it better to use `unwind-protect' and `handler-case' directly,
> >     or should we devise new syntax since the cases are numerous (I
> >     know, quite impossible to answer in general)
> 
> If there's a common pattern to your use of them, it's often a good idea to
> encapsulate that into a macro.  The name of the macro provides a useful
> abstraction, and the use of the macro helps avoid errors.

Yep.

> >   - is it wrong of us to use the condition system to propagate
> >     exceptions (an example of the need for error handling comes from
> >     the fact that when a low level request fails, we signal an error,
> >     rather than just returning some kind of error object)
> 
> This is precisely what the condition system is intended to be used for.

Yep.
From: Christian Lynbech
Subject: Re: coding style question: handler-case usage
Date: 
Message-ID: <of4rp7dgv7.fsf@chl.ted.dk.eu.ericsson.se>
I thank for the advices, I feel much better equipped to attack the
problem now. 

My problem is mostly that allthough I feel to have a fair grasp of CL,
I am not that experienced in actually coding in it, and I am (God help
our project) the lisp authority of the departement, so I felt I needed
some experienced input before decreeing largescale code
reorganizations (seems good I did).

>>>>> "Kent" == Kent M Pitman <······@world.std.com> writes:

Kent> Barry Margolin <······@genuity.net> writes:

>> It seems strange to me that you lump these two together.  HANDLER-CASE is
>> much more related to CATCH than it is to UNWIND-PROTECT.

A shortcut in my head, I think. I actually know the differences
between the two, but wasn't thinking the situation all the way
through.

A common example in our code is something like this:

      (handler-case (do-some-thing)
         (some-error (condition)
           (do-some-cleanup)
           (error condition)))

Of course, `unwind-protect' is not an obvious replacement here, since
we only only want to call `do-some-cleanup' if `do-some-thing' has
failed (one could do it with `unwind-protect', but using `handler-case'
seems cleaner). However, what really is needed is a macro to factor
out the specifics of the common pattern.

In a lot of cases, we have `error' as the discriminator, rather than
something more specific. That still needs a more carefull inspection,
I think.


------------------------+-----------------------------------------------------
Christian Lynbech       | Ericsson Telebit, Skanderborgvej 232, DK-8260 Viby J
Phone: +45 8938 5244    | email: ·················@ted.ericsson.dk
Fax:   +45 8938 5101    | web:   www.ericsson.com
------------------------+-----------------------------------------------------
Hit the philistines three times over the head with the Elisp reference manual.
                                        - ·······@hal.com (Michael A. Petonic)
From: Kenny Tilton
Subject: Re: coding style question: handler-case usage
Date: 
Message-ID: <3BC41B1B.A0F2879D@nyc.rr.com>
> Of course, `unwind-protect' is not an obvious replacement here, since
> we only only want to call `do-some-cleanup' if `do-some-thing' has
> failed (one could do it with `unwind-protect', but using `handler-case'
> seems cleaner). 

Hmmm, if you really just want to know if something completed, just set a
flag after it completes. simple. but the sequence of "handling" the
error only to issue it again straightaway and unconditionally -- yechh.
:)

I use:

(defmacro unwind-abend1 (&body abend1-Code)
   (let ((aokVar (gensym)))
      `(let (,aokVar)
          (unwind-protect
           (prog1
            (progn ,@(cdr abend1-Code))
            (setf ,aokVar t))
           (unless ,aokVar
              ,(car abend1-Code))))))

(catch :badnews
       (unwind-abend1
             (format t "~&uh-oh")
          (format t "~&lookin good!")
          (throw :badnews nil)
          (format t "~&no problemo!")))

output:

lookin good!
uh-oh
NIL
> 


kenny
clinisys
From: Barry Margolin
Subject: Re: coding style question: handler-case usage
Date: 
Message-ID: <CwZw7.39$vN6.2611@burlma1-snr2>
In article <··············@chl.ted.dk.eu.ericsson.se>,
Christian Lynbech  <·················@ted.ericsson.dk> wrote:
>A common example in our code is something like this:
>
>      (handler-case (do-some-thing)
>         (some-error (condition)
>           (do-some-cleanup)
>           (error condition)))
>
>Of course, `unwind-protect' is not an obvious replacement here, since
>we only only want to call `do-some-cleanup' if `do-some-thing' has
>failed (one could do it with `unwind-protect', but using `handler-case'
>seems cleaner). However, what really is needed is a macro to factor
>out the specifics of the common pattern.
>
>In a lot of cases, we have `error' as the discriminator, rather than
>something more specific. That still needs a more carefull inspection,
>I think.

Symbolics Common Lisp has UNWIND-PROTECT-CASE for things like this.  It's
something like:

(unwind-protect-case (do-some-thing)
  (:always ...)
  (:error ...)
  (:success ...))

It implements it using a flag to indicate whether it made it all the way
through (do-some-thing), like the unwind-protect-abend that someone else
posted.

-- 
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.
From: Marco Antoniotti
Subject: Re: coding style question: handler-case usage
Date: 
Message-ID: <y6cadyzz90p.fsf@octagon.mrl.nyu.edu>
Barry Margolin <······@genuity.net> writes:

> In article <··············@chl.ted.dk.eu.ericsson.se>,
> Christian Lynbech  <·················@ted.ericsson.dk> wrote:
> >A common example in our code is something like this:
> >
> >      (handler-case (do-some-thing)
> >         (some-error (condition)
> >           (do-some-cleanup)
> >           (error condition)))
> >
> >Of course, `unwind-protect' is not an obvious replacement here, since
> >we only only want to call `do-some-cleanup' if `do-some-thing' has
> >failed (one could do it with `unwind-protect', but using `handler-case'
> >seems cleaner). However, what really is needed is a macro to factor
> >out the specifics of the common pattern.
> >
> >In a lot of cases, we have `error' as the discriminator, rather than
> >something more specific. That still needs a more carefull inspection,
> >I think.
> 
> Symbolics Common Lisp has UNWIND-PROTECT-CASE for things like this.  It's
> something like:
> 
> (unwind-protect-case (do-some-thing)
>   (:always ...)
>   (:error ...)
>   (:success ...))
> 
> It implements it using a flag to indicate whether it made it all the way
> through (do-some-thing), like the unwind-protect-abend that someone else
> posted.

Are :ALWAYS, :ERROR, and :SUCCESS the sole available choices? If so,
what is the exact semantics of each?

Cheers

-- 
Marco Antoniotti ========================================================
NYU Courant Bioinformatics Group        tel. +1 - 212 - 998 3488
719 Broadway 12th Floor                 fax  +1 - 212 - 995 4122
New York, NY 10003, USA                 http://bioinformatics.cat.nyu.edu
                    "Hello New York! We'll do what we can!"
                           Bill Murray in `Ghostbusters'.
From: Barry Margolin
Subject: Re: coding style question: handler-case usage
Date: 
Message-ID: <9L0x7.49$vN6.3109@burlma1-snr2>
In article <···············@octagon.mrl.nyu.edu>,
Marco Antoniotti  <·······@cs.nyu.edu> wrote:
>> Symbolics Common Lisp has UNWIND-PROTECT-CASE for things like this.  It's
>> something like:
>> 
>> (unwind-protect-case (do-some-thing)
>>   (:always ...)
>>   (:error ...)
>>   (:success ...))
>> 
>> It implements it using a flag to indicate whether it made it all the way
>> through (do-some-thing), like the unwind-protect-abend that someone else
>> posted.
>
>Are :ALWAYS, :ERROR, and :SUCCESS the sole available choices? If so,
>what is the exact semantics of each?

I don't have Symbolics documentation these days, so I don't remember
precisely.  Off the top of my head I can't think of any other useful
possibilities (maybe :NEVER or :MAYBE :).

Basically, if (do-some-thing) returns normally, the :success option is
executed, whereas if a transfer of control outside the unwind-protect-case
is attempted the :error option is executed.  The macro is probably
something like:

(defmacro unwind-protect-case (form &rest cases)
  (let ((always (cdr (assoc :always cases)))
        (error (cdr (assoc :error cases)))
        (success (cdr assoc :success cases)))
    `(let ((.succeeded. nil))
       (unwind-protect
           (prog1 ,form (setq .succeeded. t))
         (if .succeeded.
             (progn ,@success)
             (progn ,@error))
         ,@always))))

-- 
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.
From: Christopher J. Vogt
Subject: Re: coding style question: handler-case usage
Date: 
Message-ID: <3BC4B01C.52AE8CEB@computer.org>
Marco Antoniotti wrote:
> 
> Barry Margolin <······@genuity.net> writes:
> 
> > In article <··············@chl.ted.dk.eu.ericsson.se>,
> > Christian Lynbech  <·················@ted.ericsson.dk> wrote:
> > >A common example in our code is something like this:
> > >
> > >      (handler-case (do-some-thing)
> > >         (some-error (condition)
> > >           (do-some-cleanup)
> > >           (error condition)))
> > >
> > >Of course, `unwind-protect' is not an obvious replacement here, since
> > >we only only want to call `do-some-cleanup' if `do-some-thing' has
> > >failed (one could do it with `unwind-protect', but using `handler-case'
> > >seems cleaner). However, what really is needed is a macro to factor
> > >out the specifics of the common pattern.
> > >
> > >In a lot of cases, we have `error' as the discriminator, rather than
> > >something more specific. That still needs a more carefull inspection,
> > >I think.
> >
> > Symbolics Common Lisp has UNWIND-PROTECT-CASE for things like this.  It's
> > something like:
> >
> > (unwind-protect-case (do-some-thing)
> >   (:always ...)
> >   (:error ...)
> >   (:success ...))
> >
> > It implements it using a flag to indicate whether it made it all the way
> > through (do-some-thing), like the unwind-protect-abend that someone else
> > posted.
> 
> Are :ALWAYS, :ERROR, and :SUCCESS the sole available choices? If so,
> what is the exact semantics of each?

From the doc: 

unwind-protect-case (&optional aborted-p-var) body-form &rest cleanup-clauses

Each cleanup-clause is considered in order of appearance and has the form 
(keyword forms ...)  keyword can be :normal, :abort or :always.  The forms in a
:normal clause are executed only if body-form finished normally.  The fors in an
:abort clause are executed only if body-form exited before completion.  The
forms in an :always clause are always executed.  The values returned are the
values of body-form, if it completed normally.