I wish to consider amending "TIP 328 Coroutines" [L1 ], 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 these reasons, 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.
The only arguments in favour of single-arg'd coroutine I've heard are:
CASE 1: (counterfactual)
Assume a [Coroutine] which generates a command taking multiple args, to implement coroutine as we have it implemented:
[Coroutine] would require no wrapping or changes to function as coroutine does now. Only yield would have to change.
To provide precisely the same functionality as yield currently does 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 } }
The predominant cost in this is that of tracing intermediate commands to avoid leakage. Even if this were not the case, the cost of calling a proc to wrap the extra args is considerable. The only alternative is to wrap the args on *each* invocation.
One can provide variable assignment by signature (or Occam-like protocol):
proc entrypoint {value args} { uplevel 1 lassign [::yield $value] {*}$args }
This is possible in current coroutine the same way, but requires the caller to form args into lists on each invocation.
jmn 2010-04-15 I totally agree. I was thoroughly dismayed by the single arg coroutine thing. It just seems to go against the grain of the 'Tcl way' - for no real advantage. If it was multi-arg'd it would present an interesting way to build some command alternatives along the lines of existing mechanisms such as 'interp alias'. Having to wrap it to achieve this is ugly enough to discourage this sort of innovation especially if the whole point of the innovation was to do so in a situation where dispatch performance matters.