如何检测Tcl协同路由的完成?
我想在Tcl中找到一种很好的方法来检测协同进程的结束。考虑:如何检测Tcl协同路由的完成?,tcl,coroutine,Tcl,Coroutine,我想在Tcl中找到一种很好的方法来检测协同进程的结束。考虑: coroutine cor apply {{} { yield 1 yield 2 yield 3 }} try { puts [cor] puts [cor] puts [cor] puts [cor] } trap {TCL LOOKUP COMMAND cor} {e} { puts "done" } 这是可行的,但它感觉像一个黑客,它是脆弱的。如果我重命名co
coroutine cor apply {{} {
yield 1
yield 2
yield 3
}}
try {
puts [cor]
puts [cor]
puts [cor]
puts [cor]
} trap {TCL LOOKUP COMMAND cor} {e} {
puts "done"
}
这是可行的,但它感觉像一个黑客,它是脆弱的。如果我重命名cor
并忘记在陷阱中重命名它,它将失败。如果我在陷阱中遗漏cor
,它将捕获不相关的打字错误
一定有更好的办法。它是什么?要检测命令是否仍然存在,请使用
info commands
并检查它返回的列表的长度。(我假设您可以保证命令名中没有glob字符;如果这是真的,那么该检查非常便宜。)
但是,如果您打算将协同例程作为生成器工作,并且只在循环中使用,那么可以让它发出信号,表明它已直接完成。为此,请使其产生一个中断
coroutine cor apply {{} {
yield [info coroutine]; # A sensible result from [coroutine]
yield 1
yield 2
yield 3
return -code break
# [tailcall break] would also work
}}
while true {
puts [cor]
}
诀窍在于,你不会屈服于破发;您使用它作为协同程序的最终结果。(您以前的协同程序使用的是收益率的结果,可能主要是出于运气。)
在写这篇文章时,我注意到了一个bug。运行协同程序的循环在8.6.8(我检查过的唯一版本)的顶层不起作用。不知道为什么。在过程/apply
上下文中,这很好(在该上下文中,将协程名称作为参数传递是很自然的):
这些不同运行方式的字节码并没有明显不同。强制解释也可以使事情正常进行,这很好地表明这是一个真正的bug
set while while
$while true {
puts [cor]
}
FWIW:tailcall break
按预期适用于顶级案例(8.6.9)。
apply {c {
while true {
puts [$c]
}
}} cor
set while while
$while true {
puts [cor]
}