How to detect the completion of a Tcl coroutine?

别来无恙 提交于 2021-02-07 21:49:48

问题


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"
}

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?


回答1:


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]
}

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]
}

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.)


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]
}


来源:https://stackoverflow.com/questions/54273578/how-to-detect-the-completion-of-a-tcl-coroutine

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!