On Wed 18 Jan 2012 20:58, Mark H Weaver <m...@netris.org> writes:

> Andy Wingo <wi...@pobox.com> writes:
>
>> "continuation marks".  We might be able to reuse their strategy in our
>> with-fluids implementation.
>
> I don't see how continuation marks could solve this problem.  They avoid
> adding more frames to the stack, but that's not enough.  The R5RS says:
>
>   A Scheme implementation is properly tail-recursive if it supports an
>   unbounded number of active tail calls.  A call is _active_ if the
>   called procedure may still return.
>
> Therefore, even if you save the old value of (current-module) cleverly
> somewhere other than the stack, these old values would still in general
> use O(n) space, where N is the number of active calls to `eval'.

There's the rub!  I believe that the way this works is to consider every
continuation as having "marks" associated with them.  For example in

  (+ (eval '(eval 'bar mod2) mod1))

the continuation may be written as

  (+ [ ])

where [ ] signifies a hole.  (Consider it to be a previous frame
pointer, coupled with a return address, if you like.)

(current-module) looks at the 'module continuation mark (or equivalent)
on a continuation.  Call-with-continuation-marks does create a new
continuation to pop marks, but only if marks are not set on that
continuation already.  If the continuation already has marks,
call-with-continuation-marks just adds/sets marks on the existing
continuation, instead of creating a new one.

So to translate it back to our world, something like

  (with-fluids ((a 2)) (with-fluids ((a 3)) (tail)))
                       ^ this doesn't create a new continuation, it just
                       overrides the marks on the previous one

It seems to be a dynamic construct (i.e., at runtime, not compile-time),
but it works for the purposes of proper tail calls.

AIUI anyway :)

Andy
-- 
http://wingolog.org/

Reply via email to