工作原理 return -TCL 中 proc 的代码 $value

How works return -code $value from the proc in TCL

我必须使用 proc Z,它 return 类似于 "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"。我可以吗?

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

因为 2TCL_RETURN 结果代码的实际值,这意味着它告诉程序外壳(即整个 Z 程序)表现得像它是对 return 的简单调用,这就是 puts "Y - out" 未被执行的原因;由于 Z 的执行,正在处理 return 异常。 (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的问题是很容易一不小心就丢错了