如何检测Tcl协程的完成? [英] How to detect the completion of a Tcl coroutine?

查看:65
本文介绍了如何检测Tcl协程的完成?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在Tcl中找到一种检测协程结束的好方法.考虑:

I'd like to find a nice way in Tcl to detect the end of a coroutine. Consider:

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 ,它将捕获不相关的错别字.

This works, but it feels like a hack and it is brittle. If I rename cor and forget to rename it in the trap, it fails. If I leave out the cor in the trap, it will catch unrelated typos.

必须有一个更好的方法.什么事?

There's got to be a better way. What is it?

推荐答案

要检测命令是否仍然存在,请使用 info命令并检查其返回的列表长度.(我假设您可以保证命令名称中没有glob字符;如果是这样,则检查非常便宜.)

To detect if a command still exists, use info commands and check the length of list it returns. (I'm assuming you can guarantee that there are no glob characters in the command's name; if that's true, the check is very cheap.)

while {[llength [info commands cor]]} {
    puts [cor]
}

但是,如果您打算将协程作为发生器工作并且仅在循环中使用,则可以使它指示直接完成.为此,请使其产生 break .

However, if you are intending the coroutine to work as a generator and only be used in a loop, you can get it to signal that it is done directly. To do that, make it produce a 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 的结果,可能主要是因为运气.)

The trick is that you don't yield the break; you use it as the terminal result of the coroutine. (Your old coroutine was using the result of the yield as that, probably principally by luck.)

在撰写本文时,我注意到了一个错误.在8.6.8(我检查过的唯一版本)的顶层,运行协程的循环不起作用.不知道为什么.在procedure/ apply 上下文中很正常(将协程名称作为参数传递是很自然的):

In writing this, I've noticed a bug. That loop to run the coroutine doesn't work at the top level in 8.6.8 (the only version I've checked with). No idea why. It's fine in a procedure/apply context (where it is natural to pass the coroutine name as an argument):

apply {c {
    while true {
        puts [$c]
    }
}} cor

这些各种运行方式的字节码看起来没有明显不同.强制解释还可以使事情正常进行,这是伟大的表明这是一个真正的错误.

The bytecode for these various ways of running does not appear meaningfully different. Forcing interpretation also makes things work, which is a great indication that this is a real bug.

set while while
$while true {
    puts [cor]
}

这篇关于如何检测Tcl协程的完成?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆