From: Donal K. Fellows on
On 05/02/2010 17:02, Paul wrote:
> The crucial point is that I want to be able to run commands contained
> in a Tcl procedure from my C code. Then be able to stop, and run
> commands in a different Tcl procedure. Then later on carry on
> executing commands in the first procedure. I'm hoping that the Tcl C
> API will support this. Conceptually it sounds simple, but in reality
> it might be more difficult.

That's definitely coroutines. (Yes, the reality of implementation has
indeed proved to be quite difficult, but we're now through that.) They
allow you to create a command, a coroutine, that works by executing
until a yield point when it stops. You can then call that coroutine
again to allow it to resume from where it stopped. You can do this as
much as you want. (You can hide the yield inside other procedures if you
want; Tcl 8.6 does all the stack management to make that Just Work™ the
way you'd hope for.)

Before you ask, there's no hope at all of backporting this feature to
any previous version of Tcl. I've heard of things being hacked together
with threads that behave similarly, but there's no way I can recommend
that level of lash-together...

Donal.
From: Paul on
On Feb 6, 4:23 pm, "Donal K. Fellows"
<donal.k.fell...(a)manchester.ac.uk> wrote:

> That's definitely coroutines. (Yes, the reality of implementation has
> indeed proved to be quite difficult, but we're now through that.) They
> allow you to create a command, a coroutine, that works by executing
> until a yield point when it stops. You can then call that coroutine
> again to allow it to resume from where it stopped. You can do this as
> much as you want. (You can hide the yield inside other procedures if you
> want; Tcl 8.6 does all the stack management to make that Just Work™ the
> way you'd hope for.)
>
> Before you ask, there's no hope at all of backporting this feature to
> any previous version of Tcl. I've heard of things being hacked together
> with threads that behave similarly, but there's no way I can recommend
> that level of lash-together...
>
> Donal.

OK - thanks.

I'm having a look at coroutines, and in particular TIP 328, and I
can't understand the section "New commands and Subcommands", and so I
have some questions. Using the example below:


proc aProc {} {
puts 1
yield
puts 2
yield
puts 3
}

proc cr {} {
aProc
aProc
}

coroutine cr aProc


I understand that the coroutine command will run aProc. The yield in
aProc suspends execution in aProc.

TIP 328 explains that a yield in the coroutine with create a commanmd
with special behaviour. It's not clear to me what the significance of
the created command is or what I have to do with it. I'm guessing I
need to to specify a proc with the same name, as above?

TIP 328 then says the coroutine returns to the caller not the creater.
What is the caller and what is the creater? Again, guessing, the
creater is the coroutine command call, and the caller the subsequent
calls to the coroutine?

The TIP then explains that coroCmdName resumes execution of the
coroutine (cr in this case), etc... That paragraph is as clear as mud
to me I'm afraid :-)

Coroutines 101! At the moment I'd like to get the above to the stage
so that it prints out 1, 2, 3.

Regards,

Paul.

From: miguel sofer on
Paul wrote:
> On Feb 6, 4:23 pm, "Donal K. Fellows"
> <donal.k.fell...(a)manchester.ac.uk> wrote:
>
>> That's definitely coroutines. (Yes, the reality of implementation has
>> indeed proved to be quite difficult, but we're now through that.) They
>> allow you to create a command, a coroutine, that works by executing
>> until a yield point when it stops. You can then call that coroutine
>> again to allow it to resume from where it stopped. You can do this as
>> much as you want. (You can hide the yield inside other procedures if you
>> want; Tcl 8.6 does all the stack management to make that Just Work� the
>> way you'd hope for.)
>>
>> Before you ask, there's no hope at all of backporting this feature to
>> any previous version of Tcl. I've heard of things being hacked together
>> with threads that behave similarly, but there's no way I can recommend
>> that level of lash-together...
>>
>> Donal.
>
> OK - thanks.
>
> I'm having a look at coroutines, and in particular TIP 328, and I
> can't understand the section "New commands and Subcommands", and so I
> have some questions. Using the example below:
>
>
> proc aProc {} {
> puts 1
> yield
> puts 2
> yield
> puts 3
> }
>
> proc cr {} {
> aProc
> aProc
> }
>
> coroutine cr aProc
>
>
> I understand that the coroutine command will run aProc. The yield in
> aProc suspends execution in aProc.
>
> TIP 328 explains that a yield in the coroutine with create a commanmd
> with special behaviour. It's not clear to me what the significance of
> the created command is or what I have to do with it. I'm guessing I
> need to to specify a proc with the same name, as above?
>
> TIP 328 then says the coroutine returns to the caller not the creater.
> What is the caller and what is the creater? Again, guessing, the
> creater is the coroutine command call, and the caller the subsequent
> calls to the coroutine?
>
> The TIP then explains that coroCmdName resumes execution of the
> coroutine (cr in this case), etc... That paragraph is as clear as mud
> to me I'm afraid :-)
>
> Coroutines 101! At the moment I'd like to get the above to the stage
> so that it prints out 1, 2, 3.


% proc aProc {} {
puts 1
yield
puts 2
yield
puts 3
}
% proc cr {} aProc
% coroutine foo cr; #1
1
% foo; #2
2
% foo
3
% foo
invalid command name "foo"

#1 creates the command 'foo' that will reawaken the coroutine, then runs
the command 'cr' until it yields.

Subsequent calls to 'foo' (#2 et al) restart the coroutine until the
next 'yield'. The command 'foo' is deleted when the coroutine returns
(as opposed to yielding).

HTH
Miguel
From: Paul on
On Feb 7, 5:46 pm, miguel sofer <mso...(a)users.sf.net> wrote:

> % proc aProc {} {
>      puts 1
>      yield
>      puts 2
>      yield
>      puts 3}
>
> % proc cr {} aProc
> % coroutine foo cr; #1
> 1
> % foo; #2
> 2
> % foo
> 3
> % foo
> invalid command name "foo"
>
> #1 creates the command 'foo' that will reawaken the coroutine, then runs
>   the command 'cr' until it yields.
>
> Subsequent calls to 'foo' (#2 et al) restart the coroutine until the
> next 'yield'. The command 'foo' is deleted when the coroutine returns
> (as opposed to yielding).
>
> HTH
> Miguel

OK, I now understand.

Thanks,

Paul.