我必须使用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中的返回,但我也希望它继续他在proc Y中的工作并放入“Y-out”。我可以做吗 ?
return
命令在概念上引发了一个异常(类型为return
,它对应于Tcl C API中的TCL_RETURN
结果代码),该异常由过程捕获(严格地说,通过执行诸如callframe管理和参数编组之类的过程的hull),其中它运行使这做一些事情。在正常的return
的情况下,它只是使程序返回该值,但是当提供-code
选项时,它可以指示程序执行其他操作;这是在从Tcl调用堆栈弹出callframe之后完成的。
因为2
是TCL_RETURN
结果代码的实际值,它意味着它告诉程序船体(即整个Z
程序)表现得像是对return
的简单调用,这就是puts "Y - out"
没有被执行的原因;由于执行Z
而处理了返回异常。 (FWIW,return -code 2
非常罕见.return -code 1
/ return -code error
更常见,因为它是一种获取错误异常的方法,这很有用,因为堆栈跟踪只是由错误异常构建的。)
您可以使用catch
或try
覆盖此处理。使用try
更容易实现这一点,因为catch
是一个相当粗略的原语。试试这个:
proc Y {} {
puts "Y - in"
try {
Z
} on return {msg} {
puts "Z told us to return '$msg'"
}
puts "Y - out"
}
如果您只是想在通话后制作一小段代码,而不是干扰,try
... finally
是正确的方法:
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
的问题在于很容易意外地丢失错误。