From: Jeff
Subject: Learning conditions
Date: 
Message-ID: <trVnd.646963$8_6.101699@attbi_s04>
 I'm trying to use conditions to solve a dilemma I have in a macro, and
am hoping a for a little help on what is "typical" and good practice
when using them.

Problem:

 I have a program that requires a significant amount of initialization
that must also be de-init'ed when done. I've devised a nice WITH style
macro that handles all this for me. Example..

    (defmacro with-stuff (&body body)
      `(when (test)
         (handler-case
             (progn
               ,@(lots-of-init-functions)
               ,@body)
           (condition () nil))
         (de-init)))

 This works out quite nicely, because if anything during the init phase
or body were to fail, the de-init code is still executed and everything
is cleaned up for the next attempt.

 However, the downside, of course, is that I can't get debugging
information about the error (sure, I can return the condition, but I
can't backtrace, etc). Am I missing something simple about conditions
or a function perhaps that will help me out?

 Simply put, I'd like my cake and to eat it, too. I want all the
debugging abilities, but I'd also like the clean-up code to execute so
I don't have to do it myself in the REPL. Much like a finally
statement. Open to suggestions, and thanks, as always ;)

Jeff M.

-- 
(a (href "http://www.retrobyte.org/"))
(a (href ···············@gmail.com"))

From: Wade Humeniuk
Subject: Re: Learning conditions
Date: 
Message-ID: <KFWnd.2075$y72.1099@clgrps12>
Jeff wrote:
>  I'm trying to use conditions to solve a dilemma I have in a macro, and
> am hoping a for a little help on what is "typical" and good practice
> when using them.
> 
> Problem:
> 
>  I have a program that requires a significant amount of initialization
> that must also be de-init'ed when done. I've devised a nice WITH style
> macro that handles all this for me. Example..
> 
>     (defmacro with-stuff (&body body)
>       `(when (test)
>          (handler-case
>              (progn
>                ,@(lots-of-init-functions)
>                ,@body)
>            (condition () nil))
>          (de-init)))
> 
>  This works out quite nicely, because if anything during the init phase
> or body were to fail, the de-init code is still executed and everything
> is cleaned up for the next attempt.
> 
>  However, the downside, of course, is that I can't get debugging
> information about the error (sure, I can return the condition, but I
> can't backtrace, etc). Am I missing something simple about conditions
> or a function perhaps that will help me out?

If you use handler-bind the stack is not unwound. You can get the debugger
and thus the backtrace (or do your own restarts).  In the example
below the debugger is invoked on a condition.  The unwind-protect will
allow the de-init function to be called even if you abort in the debugger.

when you want conditions to invoke-debugger.
(defmacro with-stuff (&body body)
     `(when (test)
        (unwind-protect
            (handler-bind
                (condition #'invoke-debugger)
              ,@(lots-of-init-functions)
              ,@body)
          (de-init))))


Wade
From: Pascal Bourguignon
Subject: Re: Learning conditions
Date: 
Message-ID: <87actbsqfr.fsf@thalassa.informatimago.com>
"Jeff" <·······@gmail.com> writes:
> [...]
>          (handler-case
> [...]
>  This works out quite nicely, because if anything during the init phase
> or body were to fail, the de-init code is still executed and everything
> is cleaned up for the next attempt.
> 
>  However, the downside, of course, is that I can't get debugging
> information about the error (sure, I can return the condition, but I
> can't backtrace, etc). Am I missing something simple about conditions
> or a function perhaps that will help me out?

UNWIND-PROTECT 

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
The world will now reboot; don't bother saving your artefacts.
From: Iain Little
Subject: Re: Learning conditions
Date: 
Message-ID: <87y8gv220t.fsf@yahoo.com>
"Jeff" <·······@gmail.com> writes:

> Problem:
>
>  I have a program that requires a significant amount of initialization
> that must also be de-init'ed when done. I've devised a nice WITH style
> macro that handles all this for me. Example..
>
>     (defmacro with-stuff (&body body)
>       `(when (test)
>          (handler-case
>              (progn
>                ,@(lots-of-init-functions)
>                ,@body)
>            (condition () nil))
>          (de-init)))
>
>  This works out quite nicely, because if anything during the init phase
> or body were to fail, the de-init code is still executed and everything
> is cleaned up for the next attempt.

If I understand what you are trying to do correctly, then you want
something like this:

(defmacro with-stuff (&body body)
  `(when (test)
     (unwind-protect
         (progn ,@(lots-of-init-functions)
		,@body)
       (de-init))))

What this does is run the DE-INIT form when the stack unwinds, whether
because the protected form has finished executing, or because an error
has been raised.

However, you could achieve a similar effect (less robustly), with:

(defmacro with-stuff (&body body)
  `(when (test)
     (handler-case (progn ,@(lots-of-init-functions)
			  ,@body)
       (serious-condition (condition)
	 (de-init)
	 (error condition)))
     (de-init)))

Cheers,


Iain
From: Jeff
Subject: Re: Learning conditions
Date: 
Message-ID: <B_Vnd.647167$8_6.11416@attbi_s04>
Iain Little wrote:

> If I understand what you are trying to do correctly, then you want
> something like this:
> 
> (defmacro with-stuff (&body body)
>   `(when (test)
>      (unwind-protect
>          (progn ,@(lots-of-init-functions)
> 		,@body)
>        (de-init))))
> 
> What this does is run the DE-INIT form when the stack unwinds, whether
> because the protected form has finished executing, or because an error
> has been raised.

Absolutely beautiful! Worked like a charm. Thank you very much!

Jeff M.

-- 
(a (href "http://www.retrobyte.org/"))
(a (href ···············@gmail.com"))