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: 1. coroutines should be able to emulate any command, not just any single-arg'd command [[generality]] 2. to implement single-arg's coroutines in multi-arg'd coroutines is simple. The converse is inefficient and difficult. [[increase in expressive power]] 3. there is no sound reason that the invocation of a coroutine should not resemble that of any other command [[principle of minimal surprise]] 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 } } ====== The preeminent 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. Counterfactual side-benefits: [::yield] stays exactly as it is. Yield to populate args becomes simpler. ====== proc yieldv {value args} { uplevel 1 [::yield $value] {*}$args } ====== <>Enter Category Here