Hi,
gotoken has send me two examples, how two use `callcc' and friends. Now
I must admit, that I cannot fiddle out, how to use them correctly, or
for what they are good for. :-(
In the past I have thought, that continuations offer a possibility, to
return from a method, and let the execution later restarts on the
point, where it was finished the last time.
Then I have learned about the Modula 2 continuations, called Coroutine
there. I was very fond of the concept behind it. Do you know it? I want
to explain it, and ask if I can do the same with Ruby's continuations?
How?
In Modula 2 I have mainly three procedures, that deal with Coroutines:
NEWPROCESS, TRANSFER and IOTRANSFER.
NEWPROCESS allocates memory for the stach, the Coroutine will use,
and additional memory for the internal states that have to
be stored.
TRANSFER(OLD, NEW) transfers the control (means execution) from the
current Coroutine, to the one contained in variable NEW. The
state of the current routine will be stored in variable OLD.
IOTRANSFER(OLD, NEW, SIGNAL) will do the same as TRANSFER(OLD, NEW).
But after occuring of signal SIGNAL, the execution will transfers back
to the old Couroutine (i.e. as if the new Coroutine has
executed TRANSFER(NEW, OLD)).
With these I can write a program like that:
MODULE HiHo;
FROM SYSTEM IMPORT WORD, ADR, SIZE, PROCESS, NEWPROCESS,
TRANSFER;
FROM Terminal IMPORT WriteString, WriteLn;
CONST maxHiHo = 17;
VAR i : CARDINAL;
HI, Ho, Main : PROCESS;
A, B : ARRAY[1..200] OF WORD;
PROCEDURE WriteHi;
BEGIN
LOOP
WriteString('Hi');
TRANSFER(Hi,Ho);
END;
END WriteHi;
PROCEDURE WriteHo;
BEGIN
LOOP
WriteString('Ho');
INC(i);
IF i > maxHiHo THEN
WriteLn;
i := 0;
END;
TRANSFER(Ho, Hi);
END;
END WriteHo;
BEGIN (*HiHo*)
i := 0;
NEWPROCESS(WriteHi, ADR(A), SIZE(A), Hi);
NEWPROCESS(WriteHo, ADR(B), SIZE(B), Ho);
TRANSFER(Main, Hi);
END HiHo.
Here the main prog will creates the two couroutines `Hi' and `Ho' and
then transfer the control to `Hi'. Can you guess what happens ;-))))
Can I do similiar thing with Ruby's continuations? Can I perhaps
emulate the three procedures NEWPROCESS, TRANSFER and IOTRANSFER?
I have tried to write a script using continuations. But it does not
what I expect:
def fib
c = nil
n, p = 0, 1
callcc {|c| return c} # (1)
n, p = n+p, p
n
end
f = fib # (2)
p "define"
p f.call
p f.call
p f.call
I would await, that I will get the sequence of Fibonacci numbers. With
evry call of `$c.call' one number. But it seems that the control will
goes back to the point (2) where I have done `f = fib', so `f' will
contain a continuation object during first `f.call', but an Integer
after the second `f.call'.
I have thougth, the execution would go back till after (1), so that the
calculation will be performed, and then the result would be returned.
But it seems also to influence the global execution. Because it goes
not only back to (1) but back to (2).
Please forgive my ignorance, but I really cannot understand how to use
Ruby's continuations. Perhaps somebody can explain me?
Thanks,
\cle.