From: Kevin L
Subject: Newbie question:  macro to wrap handler-case?
Date: 
Message-ID: <aBgLj.9246$BT1.8148@trnddc04>
I'm trying to write a "with-logged-error" macro like so:

(defmacro with-logged-error (logger body)
  "Executes args inside a handler-case and logs any errors that come up"
  `(handler-case
    ,body
    (cl:error (binda)
              (log-caught-error ,logger binda))))

log-caught-error is another macro that calls the macro log-error that
finally calls the function log-msg.  So far, everything works except in the
case that body really does throw (?) an error, in which case "binda" is
unbound.  Here is the expanded macro (everything is inside the #:batch
package):

(macroexpand '(batch:with-logged-error batch:*libcl2-logger* (format
t "Hello ~a")))
(BLOCK #:G1517
  (LET ((#:G1518 NIL))
    (DECLARE (IGNORABLE #:G1518))
    (TAGBODY
      (HANDLER-BIND
       ((ERROR
         (LAMBDA (SB-IMPL::TEMP) (SETQ #:G1518 SB-IMPL::TEMP) (GO
#:G1519))))
       (RETURN-FROM #:G1517
         (MULTIPLE-VALUE-PROG1 (FORMAT T "Hello ~a")
(SB-KERNEL:FLOAT-WAIT))))
     #:G1519
      (RETURN-FROM #:G1517
        (LET ((BATCH::BINDA #:G1518))
          (BATCH:LOG-CAUGHT-ERROR BATCH:*LIBCL2-LOGGER* BATCH::BINDA))))))

...and the error message:

The function BATCH::BINDA is undefined.
   [Condition of type UNDEFINED-FUNCTION]

I suspect the problem is *really* simple, but I'm all out of ideas.  I
really appreciate any help from out there.

From: Tim Bradshaw
Subject: Re: Newbie question: macro to wrap handler-case?
Date: 
Message-ID: <222e679b-e293-462f-ba97-e31b1718dd84@m71g2000hse.googlegroups.com>
On Apr 10, 5:21 am, Kevin L <······@tamu.edu> wrote:
> I'm trying to write a "with-logged-error" macro like so:
>
> (defmacro with-logged-error (logger body)
>   "Executes args inside a handler-case and logs any errors that come up"
>   `(handler-case
>     ,body
>     (cl:error (binda)
>               (log-caught-error ,logger binda))))

A better way to do this (in many cases) is to use handler-bind, and
log but do not handle the conditions (ie don't do a control
transfer).  This means you can insert these macros without perturbing
other code, which is cool.  Of course you may not want that.
From: Kevin L
Subject: Re: Newbie question: macro to wrap handler-case?
Date: 
Message-ID: <%HoLj.8901$_I1.5428@trnddc02>
Tim Bradshaw wrote:

> On Apr 10, 5:21 am, Kevin L <······@tamu.edu> wrote:

...[snip]...

> A better way to do this (in many cases) is to use handler-bind, and
> log but do not handle the conditions (ie don't do a control
> transfer).  This means you can insert these macros without perturbing
> other code, which is cool.  Of course you may not want that.

Thank you, you're right.  Now I have both (with-logged-error) and
(with-logged-error-squashed). :)
From: Pascal Bourguignon
Subject: Re: Newbie question:  macro to wrap handler-case?
Date: 
Message-ID: <874paai7ql.fsf@thalassa.informatimago.com>
Kevin L <······@tamu.edu> writes:

> I'm trying to write a "with-logged-error" macro like so:
>
> (defmacro with-logged-error (logger body)
>   "Executes args inside a handler-case and logs any errors that come up"
>   `(handler-case
>     ,body
>     (cl:error (binda)
>               (log-caught-error ,logger binda))))
>
> log-caught-error is another macro that calls the macro log-error that
> finally calls the function log-msg.  So far, everything works except in the
> case that body really does throw (?) an error, in which case "binda" is
> unbound.  Here is the expanded macro (everything is inside the #:batch
> package):
>
> (macroexpand '(batch:with-logged-error batch:*libcl2-logger* (format
> t "Hello ~a")))
> (BLOCK #:G1517
>   (LET ((#:G1518 NIL))
>     (DECLARE (IGNORABLE #:G1518))
>     (TAGBODY
>       (HANDLER-BIND
>        ((ERROR
>          (LAMBDA (SB-IMPL::TEMP) (SETQ #:G1518 SB-IMPL::TEMP) (GO
> #:G1519))))
>        (RETURN-FROM #:G1517
>          (MULTIPLE-VALUE-PROG1 (FORMAT T "Hello ~a")
> (SB-KERNEL:FLOAT-WAIT))))
>      #:G1519
>       (RETURN-FROM #:G1517
>         (LET ((BATCH::BINDA #:G1518))
>           (BATCH:LOG-CAUGHT-ERROR BATCH:*LIBCL2-LOGGER* BATCH::BINDA))))))
>
> ...and the error message:
>
> The function BATCH::BINDA is undefined.
>    [Condition of type UNDEFINED-FUNCTION]
>
> I suspect the problem is *really* simple, but I'm all out of ideas.  I
> really appreciate any help from out there.

The problem is with your BATCH:LOG-CAUGHT-ERROR macro, not with
WITH-LOGGED-ERROR.  Try:

(macropexpand '(BATCH:LOG-CAUGHT-ERROR BATCH:*LIBCL2-LOGGER* BATCH::BINDA))

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Until real software engineering is developed, the next best practice
is to develop with a dynamic system that has extreme late binding in
all aspects. The first system to really do this in an important way
is Lisp. -- Alan Kay
From: Kevin L
Subject: Re: Newbie question:  macro to wrap handler-case?
Date: 
Message-ID: <KJoLj.8902$_I1.2259@trnddc02>
Pascal Bourguignon wrote:

> Kevin L <······@tamu.edu> writes:
> 
>> I'm trying to write a "with-logged-error" macro like so:
>>
>> (defmacro with-logged-error (logger body)
>>   "Executes args inside a handler-case and logs any errors that come up"
>>   `(handler-case
>>     ,body
>>     (cl:error (binda)
>>               (log-caught-error ,logger binda))))
>>

...[snip]...

> The problem is with your BATCH:LOG-CAUGHT-ERROR macro, not with
> WITH-LOGGED-ERROR.  Try:
> 
> (macropexpand '(BATCH:LOG-CAUGHT-ERROR BATCH:*LIBCL2-LOGGER*
> BATCH::BINDA))

You are right, thank you!  The log-caught-error macro wasn't handling its
&rest argument(s) correctly.