From: Donal K. F. <don...@ma...> - 2010-04-16 09:52:24
|
On 16/04/2010 09:59, Twylite wrote: > For what it's worth, I think the follow snippet does the same as Colin's > Case 2 (but without cleanup): > > rename ::coroutine ::tcl::coroutine > proc ::coroutine {name cmd args} { > set result [uplevel 1 [list ::tcl::coroutine __C_$name $cmd] $args] > uplevel 1 [list proc $name {args} [subst { tailcall {__C_$name} > \$args }] ] > return $result > } That won't work because [info coroutine] returns the real coroutine name (and, as you noted, there isn't anything in there to deal with coroutine deletion, which is quite tricky because it can happen either from inside out or outside in). Tidying up all the loose ends to make multi-value-accepting coroutine reentry work transparently is just a bunch of work and that's why it would be better if this was all done in the core implementation. It's not about deep semantics, it's about the shallow business of syntax and immediate semantics. :-) I'm not sure what the right syntax for doing this "in core" is. Perhaps the right thing is to augment [coroutine] to "declare" what the argument syntax for that coroutine's command is (and making [yield] return those arguments as a list) since then we could easily have the case where that is omitted be the current behaviour? Thus: coroutine foobar -arguments {x y} apply {ctr { lassign [yield] x y while 1 { lassign [yield [expr {$ctr + $x + $y}]] x y incr ctr } }} 1 (I thought about making those be local variables that are automatically bound; that would be cool, but would stop other things like being able to use arbitrary commands as coroutine implementations. Having [yield] return a list when -arguments is given is probably best overall.) Donal. |