我想在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"
}
这可行,但感觉像是破解,而且很脆弱。如果我重命名
cor
并忘记在陷阱中重命名它,它将失败。如果我在陷阱中遗漏了cor
,它将捕获不相关的错别字。必须有更好的方法。它是什么?
最佳答案
要检测命令是否仍然存在,请使用info commands
并检查其返回的列表长度。 (我假设您可以保证命令名称中没有glob字符;如果是这样,则检查非常便宜。)
while {[llength [info commands cor]]} {
puts [cor]
}
但是,如果您打算将协程用作生成器并且仅在循环中使用,则可以使它发出信号来直接完成。为此,使其产生
break
。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]
}
诀窍是您不对中断使用
yield
;您将其用作协程的最终结果。 (您的旧协程使用的是yield
的结果,可能主要是出于运气。)在撰写本文时,我注意到了一个错误。在8.6.8(我检查过的唯一版本)的顶层,运行协程的循环不起作用。不知道为什么。在过程/
apply
上下文中很好(将协程名称作为参数传递是很自然的):apply {c {
while true {
puts [$c]
}
}} cor
这些各种运行方式的字节码看起来没有明显不同。强制解释还可以使事情正常进行,这很好地表明了这是一个真正的错误。
set while while
$while true {
puts [cor]
}
关于tcl - 如何检测Tcl协程的完成?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54273578/