I wish to consider amending "TIP 328 Coroutines" http://www.tcl.tk/cgi-bin/tct/tip/328.html , along these lines:
Invocation of a coroutine should accept multiple arguments, those arguments should be returned to the coroutine's ::yield as a list of actual parameters.
The current implementation forbids invoking a coroutine with more than one argument. I have found, in practice, that many of my coroutine invocations are naturally like other command invocations, and take multiple arguments.
The case for providing multi-arg'd coroutines is:
For this reason, the core should be modified to accept multiple actual parameters to a coroutine invocation, ::yield should be modified to resemble ::yield2 below, and a new interface ::yieldm should be created to return the actual parameter list as it's passed.
-- Demonstration of point 2 --
CASE 1: (counterfactual)
Assume a Coroutine which generates a command taking multiple args, to implement coroutine as we have it implemented:
proc coroutine {name command args} { set ns [namespace qualifiers $name] if {$ns eq ""} { set ns [uplevel 1 {namespace current}] } set name [namespace tail $name] Coroutine ${ns}::$name $command {*}$args }
To provide precisely the same functionality as yield it is necessary to strip off a single layer of list:
proc ::yield2 {value} { return [lindex [::yield $value] 0] }
No other changes are necessary. More likely, one would define ::yield like that, and create a new ::yield-variant which returned the whole invocation arg list.
CASE 2: [Coroutine] in [coroutine] - implementing multi-arg'd coroutines over singe-arg'd coroutine
proc Coroutine {name command args} { set ns [namespace qualifiers $name] if {$ns eq ""} { set ns [uplevel 1 {namespace current}] } set name [namespace tail $name] set coco [::coroutine ${ns}::_C$name $command {*}args] trace add command ${ns}::_C$name delete "rename ${ns}::name {}" proc ${ns}::$name {args} { set name [lindex [info level 0] 0] set ns [namespace qualifiers $name] if {$ns eq ""} { set ns [uplevel 1 {namespace current}] } set name [namespace tail $name] ${ns}::_C$name $args } }
Counterfactual side-benefits: ::yield stays exactly as it is.
Yield to populate args becomes simpler.
proc yieldv {value args} { uplevel 1 [::yield $value] {*}$args }