Re: Mysteries of unwind-protect

"Tim Bradshaw (as tfb at tfeb dot org)" <[email protected]>
Newsgroups gmane.lisp.lispworks.general
Message-ID <[email protected]>
On 15 Jan 2026, at 14:56, Yuri Davidovsky <[email protected]> wrote:
> 
> (UNWIND-PROTECT
>     (SETQ V0 (+ V0 1.0D0)) ; I removed the incf as it was littering the macroexpand
>   (LET* ((#:FORM3987 V) (#:|Store-Var-3986| V0))
>     (SETF::\"COMMON-LISP\"\ \"AREF\" #:|Store-Var-3986| #:FORM3987 0)))

These aren't the droids you're looking for.  unwind-protect is entirely uninteresting if it only has one form, because then there are no unwind forms.  And since it's a special operator, macroexpand isn't really helpful.  The question I don't (may be, didn't) understand is why the unwind forms seem not to listen to the things the compiler should know.

And I think perhaps I do understand now:

> (defun foo ()
    (let ((v 1))
      (unwind-protect
          (/ v 0)
        (incf v))
      v))
foo

> (compile *)
foo
nil
nil

> (foo)

Error: Division-by-zero caused by / of (1 0).
  1 (continue) Return a value to use.
  2 Supply new arguments to use.
  3 (abort) Return to top loop level 0.

Type :b for backtrace, or :c <option number> to proceed, or :a to abort.
Type :bug-form "<subject>" for a bug report template or :? for other options.

1 > :n 3
Call to foo

1 > (setf v #c(1.0 2.0))
#C(1.0 2.0)

1 > :c

Supply a form to be evaluated and used: 1
#C(2.0 2.0)


In other words, the unwind forms in unwind-protect may well happen in an environment where things it might seem safe to assume are not, in fact, true, because there's been a trip through the debugger.

--tim
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.