guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Procedure proposal: call-with-escape-procedure


From: Marius Vollmer
Subject: Re: Procedure proposal: call-with-escape-procedure
Date: 04 Mar 2001 00:27:49 +0100
User-agent: Gnus/5.0803 (Gnus v5.8.3) Emacs/20.7

Marius Vollmer <address@hidden> writes:

> I do like the theoretical power of call/cc, but I'm wary of its
> practical consequences.  [...]

Well, after thinking more about this, I can no longer find something
significant wwrong with call/cc.  (I can't see how to allow call/cc
while still stack allocating environment frames, but that's only the
implementation.)

Call/cc does not introduce subtle bugs into existing programs, like
multi-threading might.  Someone who uses call/cc has to make sure that
the rest of the code can cope with that, but that should generally be
no problem.  When call/cc is used in a non-confusing way, for example
to implement escape points or coroutines, there are no bad semantic
consequences for unrelated code.  When it is used in more advanced
ways, for non-deterministic backtracking algorithms, say, than the
affected code is very probably written to deal with it.

One issue is the interaction between call/cc, dynamic-wind, and
resource management.  In the presence of full call/cc, you can't know
when it is the last time that a `leave' thunk of dynamic-wind is
called.  Thus, you can't perform non-undoable operations there, like
closing a channel to a file (and losing the state of where you are in
the file, etc).  Is that a problem?

I don't think so, actually.  Resource management should be left to the
GC.  The purpose of closing a file channel is not so much to free a
file descriptor slot in the kernel, it is to flush the buffers and
inidicate that no further actions are expected on that file channel,
thereby allowing some error checking.

The cleaning up of resources should be done by the GC, in all cases.
Synchronous, state changing operations on resources should not be
considered cleanup operations.  That's the reason why
call-with-output-file is written the way it is.

On the other hand, dynamic-wind can be seen as creating a new dynamic
environment for the code in its `body' thunk.  Entering and leaving
this environment can be dealt with easily.  That's why call
with-output-to-port is written the way it is.

If you follow these argument, restricting the use of call/cc by
providing less-powerful alternatives like call/ec then only makes
sense because full call/cc is hard to implement efficiently.  Is that
true?  Unfortunately, I do think so, and I also think that allowing
full call/cc also affects the efficience of code that does not use it.

This is mainly so because mutable lexical bindings can not be
allocated on a stack.  Luckily, mutated lexical bindings can be
detected at compile-time, and are hopefully relatively rare.  For
function arguments, we can have the callee copy mutated arguments into
a heap-frame on function entry.  That is, we can still use a
stack-based calling convention, and use the stack-copying
implementation of continuations.  That would shift most of the cost of
continuations to the actual use of them, which is the right thing, in
my opinion.

This makes it useful to have call/ec and a separate threading
mechanism in addition to continuations.


Ok, so much for my general thoughts about continuations.  They don't
affect Guile much right now, but I'm now convinced that we don't have
to suffer from continuations when thinking about a native code
compiler.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]