如何在TCL中从proc返回-code $ value

时间:2019-03-08 10:57:46

标签: return tcl proc

我必须使用proc Z,它返回的内容类似于“ return -code 2” $ something,但是我不知道它是如何工作的。

proc X {} {
    puts "X - in"
    Y
    puts "X - out"
}
proc Y {} {
    puts "Y - in"
    Z
    puts "Y - out"
}
proc Z {} {
    puts "Z - in"
    return -code 2 "some value"
    puts "Z - out"
}
X

输出为:

X - in
Y - in
Z - in
X - out

我无法在proc Z中更改return,但我也希望它继续在proc Y中继续他的工作并放入“ Y-out”。我可以吗?

1 个答案:

答案 0 :(得分:2)

从概念上讲,return命令会引发一个异常(严格地,通过以下方式捕获)(类型为return,它对应于Tcl C API中的TCL_RETURN结果代码)过程外壳,它执行诸如调用框架管理和参数编组之类的操作),并在其中运行以使其执行某些操作。在普通return的情况下,它只是使过程返回该值,但是当提供-code选项时,它可以指示过程执行其他操作。这是在 从Tcl调用堆栈中弹出呼叫帧之后完成的。

因为2TCL_RETURN结果代码的实际值,这意味着它告诉过程外壳(即整个Z过程)的行为就像是对return的简单调用,这就是为什么未执行puts "Y - out"的原因; Z的执行导致正在处理返回异常。 (FWIW,return -code 2很少见。return -code 1 / return -code error更为常见,因为它是引发 error 异常的一种方式,之所以有用,是因为堆栈跟踪仅由错误异常构建。)

您可以使用catchtry覆盖此处理。使用try来实现此目的要容易一些,因为catch是一个相当广泛的基元。试试这个:

proc Y {} {
    puts "Y - in"
    try {
        Z
    } on return {msg} {
        puts "Z told us to return '$msg'"
    }
    puts "Y - out"
}

如果您只是想在调用后编写一小段代码,但又不想干扰,那么tryfinally是正确的方法:

proc Y {} {
    puts "Y - in"
    try {
        Z
    } finally {
        puts "Y - out"
    }
}

如果您使用的是Tcl 8.5(或更早版本),则不会有try。这是catch的版本:

proc Y {} {
    puts "Y - in"
    set code [catch {
        Z
    } msg]
    if {$code == 2} {
        puts "Z told us to return '$msg'"
    }
    puts "Y - out"
}

catch的问题在于,很容易意外丢失错误。