====== # returns an unused command name proc gensym {prefix} { tailcall apply {{prefix} { string cat $prefix[llength [info commands $prefix*]] }} $prefix } # creates an anonymous coroutine. New features: # . avoid polluting the global namespace # . return a FQ command name, usable in any context namespace eval ::goro {} proc go {cmd args} { set name [gensym ::goro::#] coroutine $name $cmd {*}$args return $name } ====== Credit for the above code goes to [aspect]. The odd construct with `tailcall apply` is so that [info commands] will be executed in the caller's namespace. [MS] finds that this construct has a big problem: name reuse. Some code could be holding onto a coro handle, and wanting to find out if it still exists via [[info command]] (or just waiting to error out, intentionally or not). If the coro exited and a new one was created with the same name, chaos could ensue ... So my proposal is to either use a global counter (possibly in a namespace). If we really cannot live with a global var, we could do: ====== coroutine gensym apply {{} { set prefix [yield] while 1 { set name $prefix[dict incr counters $prefix] if {[llength [uplevel 1 [list info commands $name]]]} continue set prefix [yield $name] } }} ====== [aspect]: great observation! I've previously used a `gensym` like the above, but switched to the "less stateful" one above for exploring CSP. The risk of hard-to-diagnose errors is a Very Good Reason to avoid name reuse. [MS]: modified `gensym` to take care of emiliano's observation in the chat: we should verify that the command does not already exist. [PYK] 2015-11-11: The `tailcall apply` trick doesn't work as described because `[apply]` evaluates a 2-elemen procedure specification, evaluates its procedure in the [global] scope. It could be reworked to use `[uplevel]` to get the namespace of the caller, but in that case it would be simpler just to uplevel the `[info comamnds]` call, and maybe use `[namespace which]` instead. I sometimes reach for `[info cmdcount]` to address the issue of name reuse. Combining these ideas leads to an implementation like ====== proc gensym prefix { while {[uplevel [list namespace which $prefix[ set cnt [info cmdcount]]]] ne {}} {} return $prefix$cnt } ====== `go` still creates a named `[coroutine]`, not an anonymous one, and I would typically just use `coroutine` directly with a `gensym` substitution as the first argument so that the results of that first `coroutine` call would be available as needed: ====== set res [coroutine proc1 coro[gensym] arg1 arg2 ...] ====== <> Concurrency