The case for providing multi-arg'd coroutines is:
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 }