Re: Continuations in Common Lisp (with apologies)

From: Kent M Pitman (pitman_at_nhplace.com)
Date: 02/10/05


Date: Thu, 10 Feb 2005 17:40:10 GMT


"William D Clinger" <cesuraSPAM@verizon.net> writes:

> Control effects, like side effects, should be documented.

But sometimes they are not.

There are tools that I've seen written in Scheme that do backtracking,
for example, by checkpointing the state at various points in ways that
are not easily explained to users. In fact, the value of the tool is
that it hides the control aspects and just tells you to rely on the magic
of the abstraction.

Explaining to a user how these tools will interact with others that
inhibit such checkpointing (permitting only one exit) is often difficult.

> Undocumented control effects, like undocumented side
> effects, are properly regarded as bugs or as malicious.
> UNWIND-PROTECT protects against a fairly specific control
> effect, which I'll describe below. [...]
>
> There is only one kind of control effect that can cause
> a problem: a continuation that is captured within the
> dynamic extent of the UNWIND-PROTECT is returned out of
> the UNWIND-PROTECT, or is stored within a variable or
> data structure that outlives the dynamic extent of the
> UNWIND-PROTECT, and is then invoked after control has
> left the UNWIND-PROTECT.

Here's the problem:

UNWIND-PROTECT is fundamental to a lot of programming.

As I'm reading it, you SEEM to expect programs containing
UNWIND-PROTECT to be case-marked in a way that says "maybe you don't
want to go here". (Don't let me put words in your mouth, Will. If
you are saying something else, just say it. I'm just telling you what
I'm hearing so you'll know whether you need to respond here.)

My point is that I worry that the end effect will either be "don't use
Kent's code if you like continuations, because it's riddled with
UNWIND-PROTECT". Which sounds a lot to me like saying "UNWIND-PROTECT
is really second-class and should be avoided because it doesn't work
well with its so-called friends." Which sounds a lot like "This
language isn't designed to allow you to comfortably use all of its
tools in a single program without them tripping over each other."
At least, that's the train of thought I tend to go down as I try to
think about the whole "ecology" of the thing.

I'm shooting from the hip here, a bit, since I haven't had the time I
promised to sit down and think in depth. But I do find myself nervous
about this matter. And I am writing this not to assert you're wrong
but to pick your brain on why you think you're right, in hopes it will
inform my later thought on this.

This kind of meta-problem was a big issue for PROG + RETURN in Common
Lisp for a while, and was finally possible to solve with the issue of
TAGBODY because the notion of named returns could be transparently
inserted in macros, and very few macros needed to export a visible tag
(usually NIL) that would be captured by some client environment.

But the problem with UNWIND-PROTECT and CALL/CC seems to me to be that
they are a little like the "unstoppable force" and the "impenetrable barrier".
Fine concepts considered in isolation, but can't play well together in the
real world. One has to be first-class and the other, at best, second-class
if not left out entirely.

My problem is that I have tons of need for UNWIND-PROTECT and little
need for CALL/CC that isn't handled neatly by stack-CATCH like CL has,
which is not troubled by CALL/CC. I have no desire to piss off
programmers who don't like my style, and I assume they have no desire
to piss me off. But it's the job of language designers to create an
arena in which people can mix and match components in a predictable
way WITHOUT coordinating directly. It should be enough to have read
the manual and to see how things are supposed to work. And it seems
to me you either need to say "feel free to use UNWIND-PROTECT" or
"don't use UNWIND-PROTECT" or "if you use UNWIND-PROTECT, you MUST
document the fact even though you may think it's an internal detail"
or "if you use CALL/CC you MUST document the fact" even though you may
think it's an internal detail.

I think you're right that control abstractions need to be documented, but
CALL/CC is a control abstraction. So maybe you're saying that all uses
of CALL/CC should be documented. ;) I wonder if other Schemers agree.
Or I wonder if maybe you didn't mean to say that.

Again, please don't let me speak for you. I'm just offering some issues
for you to opine on.



Relevant Pages

  • Re: Continuations in Common Lisp (with apologies)
    ... >>to compare with other languages having full continuations. ... We now look at the unwind-protect in Common Lisp, ... Since unwind-protect is all about control transfers, ... we need to examine how control behaves in CL and CL+. ...
    (comp.lang.lisp)
  • Re: Three questions about UNWIND-PROTECT
    ... example the cleanup form is executed first ... and then the transfer of control happens. ... executed and *access-count* is still going to have ...
    (comp.lang.lisp)
  • Re: Continuations in Common Lisp (with apologies)
    ... call/cc as defined by Scheme is not it. ... Scheme's call-with-current-continuation procedure ... is standard, and plays nicely with unwind-protect. ...
    (comp.lang.lisp)
  • Re: Continuations in Common Lisp (with apologies)
    ... Unconstrained CALL/CC makes it impossible to know when to run ... UNWIND-PROTECT cleanup forms. ... (let ((continuation nil) ... (funcall continuation nil))) ...
    (comp.lang.lisp)
  • Re: Continuations in Common Lisp (with apologies)
    ... > is standard, ... I'd like to check my understanding: ... plays well with your implementation of unwind-protect. ... call/cc and/or dynamic-wind in their raw form in practice? ...
    (comp.lang.lisp)