From: Joe E. <jen...@fl...> - 2010-08-28 18:37:20
|
[ Those sick of this thread, please scan ahead to TL;DR at bottom ] Neil Madden wrote: > [...] > [yield] and [yieldm] are both trivially inter-defineable. It just > depends which side of the channel you like to do the extra work. > > [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] [...] > | 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. Alas, it's actually quite a bit less involved. I tried doing something similar -- implementing variadic coroutine commands given single-argument ones as a primitive -- starting with essentially the same thing as you have above. Trying to get all the details right, though -- namespace niceties, proper propagation of return codes, cleaning up the wrapper command when the wrappee returns normally -- it ballooned to several screensful. And I never did manage to get all the details right. > [yield] in terms of [yieldm]: > | [... snipped ...] Ditto here. However: > Incidentally, [yieldto] doesn't make this any neater, regardless of how many > arguments it resumes with. As you note in a later message, it actually does make it neater. Quite a bit neater: > | proc yield {{arg ""}} { > | set args [yieldto return -level 0 $arg] > | while {[llength $args] > 1} { > | set args [yieldto return -code error -level 0 "wrong # args..."] > | } > | return [lindex $args 0] > | } Unless I'm missing something obvious, that manages to get *all* of the details right. (Mostly because doing things that way there are fewer extraneous details like namespace niceties to worry about.) There's a *slight* operational difference between this [yield] and the current implementation, but the difference is semantically negligible. << TL;DR: Start Here >> That settles the isue for me: * coroutine commands should be variadic; * the inner return value of [yieldto] should be the list of arguments passed to the resumption command; and * for the common cases where zero or one arguments are needed, [yield] can be defined (and perhaps even implemented) as above. This approach Feels Right to me. --Joe English jen...@fl... |