Re: [Scheme-reports] Comments on draft 6 about call/cc Alex Shinn 26 Feb 2012 06:58 UTC

Hi Oleg,

Thanks again for your comments, I've replied inline below.

On Mon, Feb 20, 2012 at 12:04 AM,  <oleg@okmij.org> wrote:
>
> I'd like to draw attention to one part of R5RS that was in need of
> clarifications or revisions -- call/cc. It is one of the most
> confusing features of Scheme, for a good reason: it is a wrong
> abstraction.
>
> The new features of R7RS, exceptions and parameters --
> make clarifications or revisions more urgent. The interactions of
> call/cc with exceptions and dynamic binding are highly non-trivial and
> confusing, leading to unexpected consequences such as memory leaks,
> exceptions handled with unexpected handlers or the files that should
> be closed remaining open.

"Confusing" is rather subjective.  Exceptions and parameters
are defined in terms of call/cc and dynamic-wind, so the
semantics are at least unambiguous - parameters are in fact
strictly a library feature.

I think the problem here is that the interaction of call/cc and
dynamic-wind itself can be confusing, and it is for this reason
that call/cc is not considered an every day tool but a basis for
defining simpler control operators.

> At the very least, I would like to see the
> Report warning about the problems caused by call/cc and advising
> against its use unless strictly necessary. Ideally, I'd like to see
> call/cc relegated to optional features, with opening a discussion for
> better abstractions. (I have a few in mind.)

The WG2 has already decided to include some form of
delimited continuation in the "Large" language, and is in
fact looking for new volunteers for that effort.  We'd be
thrilled to have whatever help you can contribute there.

For the R7RS "Small" language report, making call/cc
optional is a very big step, and we would need a better
abstraction already available and widely used.  I think as
a standard the correct path would be to make the best
alternative possible available in R7RS "Large", encourage
its use, and then consider making call/cc optional in R8RS.

> The primitive call/cc has been added to Scheme when little has been
> known about expressiveness of undelimited and delimited
> continuations. [I'm generous: a good alternative -- generators -- and
> their efficient implementations have been known before Scheme was
> invented.] Now we know that capturing undelimited continuations gives
> us, per se, little power. We cannot even implement exceptions -- let
> alone more interesting effects such as state or non-determinism --
> without using other features such as mutation.

And yet Scheme has mutation.  I don't think it's fair to
consider features in isolation, but to view Scheme as
a complete language, and consider the interaction of all
features provided.

With mutation, call/cc can implement delimited continuations.
The inverse is not so - delimited continuations can't
implement call/cc nor many uses of it such as amb.

Thus call/cc makes Scheme strictly more expressive
than delimited continuations.  Since it can be used to
implement delimited continuations as a library, it is
preferable from a theoretical standpoint.  From a practical
standpoint implementations are free to implement the
delimited conts more efficiently (and in fact use the same
infrastructure to implement call/cc by wrapping a delimiter
around the whole program).  So in the long term I think
it makes the most sense to provide both, treat call/cc
as more fundamental, yet encourage use of delimited
conts wherever possible.

> Using call/cc has many practical drawbacks -- for example, huge
> resource leak. Capturing the whole continuation (where only a prefix
> is really needed) prevents objects referenced from the unneeded suffix
> of the continuations from being garbage collected.

I understand how this can be an issue in theory, but
are there real-world applications where this has been
a problem?  It seems to me that when using call/cc
for delimited cont type control flow, the suffix will remain
constant and will be needed eventually anyway.  When
using call/cc for undelimited control flow, this is something
that would not have been possible otherwise anyway,
and is in a sense a pay-as-you-go feature.

> All the uses of call/cc in practical programs that I'm aware of are
> better served by more appropriate operations. For example, it has
> been frequently observed that in most all the cases a captured
> continuation is invoked at most once. As shown by Dybvig et al and
> Feeley, one-shot continuations are much more efficient to implement.

Yes, I think one-shot continuations should also be
included in the large language, following the same
arguments as delimited continuations - they should
be used wherever possible, although in some
implementations they may simply be implemented
in terms of call/cc.

> Ironically, the illustrating examples of call/cc in R7RS [p49 of the
> draft 6] are better implemented with now provided exceptions. The
> draft retains the phrase [p49, middle of the first column]
> from R5RS that ``A common use of
> call-with-current-continuation is for structured, non-local exits from
> loops or procedure bodies''. I'd like to propose to add the phrase
> ``Non-local exists are so common that R7RS provides better tools for
> that -- exceptions.''

There are those who would disagree on general
style principals, that exceptions should never be
used for non-exceptional situations.  call/cc with
a cont named "return" is a common idiom, and
more obvious to me than

  (guard (exn (else exn))
     ...
     (raise <result>))

although of course call/ec can be more efficient.

> My second suggestion is to modify the phrase
> ``The call-with-current-continuation procedure allows Scheme
> programmers to do that by creating a procedure that acts just like the
> current continuation.'' [p 49, middle of the first column]
> to say that the procedure that acts like a current continuation is,
> like the error or raise procedures, is special in that it never
> returns and so cannot be meaningfully composed.

I think that's reasonable, we can add this and consider
additional warnings about using call/cc as you suggest
(I've created ticket 352 for this).

> I would like the discussion of call/cc to mention non-trivial
> interactions of call/cc with exception handlers and dynamic binding
> (parameters) and the danger of memory leak.

We can and should provide examples where this
interaction is surprising.  I think we'd need more
data on memory leaks to mention them in the standard.

--
Alex

_______________________________________________
Scheme-reports mailing list
Scheme-reports@scheme-reports.org
http://lists.scheme-reports.org/cgi-bin/mailman/listinfo/scheme-reports