[Replying to list too this time...]

On 27 August 2010 09:21, Twylite <twylite@crypt.co.za> wrote:
 Hi,
>>> In Tcl, only [socket -server] and [trace] seem to concat/lappend further
>>> arguments.  Did I miss other concat/lappend'ing back-callers?
>> expr {func($one, $two, $three)}
> Will that substantially boost the number of cases?
socket -server, trace (as already identified)
interp bgerror
chan event / fileevent
chan copy -command / fcopy -command
http::geturl -command
lsort -command
::tcl::mathfunc::*
::tcl::mathop::*
unknown, namespace unknown
(tk and ttk widget) -xscrollcommand, -yscrollcommand
(ttk widget) -takefocus
scale -command
scrollbar -command
tk_fontchooser -command

We've been around this argument enough times now. We all know the pros and cons: [yield] and [yieldm] are both trivially inter-defineable. It just depends which side of the channel you like to do the extra work.

As a proof of this claim -- defining each in terms of the other:

[yieldm] in terms of [yield]:

interp alias {} yieldm {} yield
proc resume {coro args} { tailcall $coro $args }
proc lambda {params body} { list apply [list $params $body] }
# Update [info coroutine]
set map [namespace ensemble configure info -map]
dict set map coroutine [lambda {} { list resume [tcl::info::coroutine] }]
namespace ensemble configure info -map $map
# Update [coroutine]
rename coroutine ::tcl::coroutine
proc coroutine {name cmd args} {
    interp alias {} $name {} resume $name.coro
    trace add command $name delete [lambda {cmd args} { rename $cmd.coro "" }]
    ::tcl::coroutine $name.coro $cmd {*}$args
}

That's more involved than you probably really need. Even so, I count only 10 lines of code. [Edit: should be 11, once I learn to count properly.]

[yield] in terms of [yieldm]:

proc yield {{arg ""}} { lindex [yieldm $arg] 0 }
proc only1 {cmd arg} { tailcall $cmd $arg }
# Update [info coroutine]
set map [namespace ensemble configure info -map]
dict set map coroutine [lambda {} { list only1 [tcl::info::coroutine] }]
namespace ensemble configure info -map $map
# Update [coroutine]
rename coroutine ::tcl::coroutine
proc coroutine {name cmd args} {
    interp alias {} $name {} only1 $name.coro
    trace add command $name delete [lambda {cmd args} { rename $cmd.coro "" }]
    ::tcl::coroutine $name.coro $cmd {*}$args
}

Almost identical code! Either we accept only a single argument and have to take pains to wrap all multi-argument uses, or we accept multiple args and have to take pains to ensure correct error messages when we only want a single argument. Of course, in most cases you don't need to be this anal about the details: a simple [list resume $coro] will do in one case, and a simple [lindex [yieldm] 0] will do in the other. There is no principled reason for choosing one or the other as primitive. My vote would be to just include them both to stop this silly bickering.

Incidentally, [yieldto] doesn't make this any neater, regardless of how many arguments it resumes with.

PS - Have the options for tcl-core changed recently? I no longer receive copies of my own messages sent to the list.

-- Neil