3

有没有一种简单的方法可以在 Tcl 中展开堆栈?我有一个奇怪的问题,我必须回到一个特定的堆栈帧,字面意思。我可以使用info命令获取所有帧信息,但要实际获取特定帧,我必须在每个过程中设置一些局部变量并相应地检查它们。我想知道是否有更简单的方法。

4

3 回答 3

4

如果您需要获取代码来执行非本地返回(即,跳过几个级别),您可以从 8.5 开始-level使用return. 看这个例子:

proc foo-a {} {
    puts a-in
    foo-b
    puts a-out
}
proc foo-b {} {
    puts b-in
    foo-c
    puts b-out
}
proc foo-c {} {
    puts c-in
    foo-d
    puts c-out
}
proc foo-d {} {
    puts d-in
    bar
    puts d-out
}
proc bar {} {
    puts bar-in
    return -level 3
    puts bar-out
}
foo-a

这是通过抛出一种特殊的异常来实现的;细节相当隐蔽。或者,如果您有 8.6 或它们的脚本实现,您也可以使用trythrow请参阅Tcler 的 Wiki,了解在讨论 8.6 中的代码期间使用的 Tcl 代码)。

对于较旧的 Tcl 版本,最简单的机制是使用return -code 42并将一些代码放置catch在自定义异常的堆栈上,并确定它是否是魔法值(这里是 42;它将是 的结果catch)并适当地响应。这可能非常有效,但也很混乱。这就是为什么 8.5 及更高版本为您提供更易于使用的工具的原因。

于 2012-04-05T10:40:49.897 回答
3

简短的回答是你可能会更好地重新考虑你的设计。

更长的答案是,唯一真正的方法(我能想到的)是抛出一个错误并将其重新捕获到您需要停止它的级别。当然,除了在调用堆栈中一直检查变量的不那么火爆的方式。然而,对控制流使用错误是……不好的形式。

于 2012-04-05T00:26:44.450 回答
1

如果您愿意成为最前沿的人,协程(在 8.6 中可用)可能会满足您的需求。

否则,您可能会尝试记录您在那里时需要达到的例程级别(即,将全局变量设置为 [info level]),然后在更深的 proc 中,[uplevel] 到那个绝对堆栈帧。就像是

proc need-to-be-here {} {
   set ::myframe [info level]
   deeper-calls
}

proc deepest-call {} {
   uplevel #$::myframe {what I need to do}
}

(未经测试)

于 2012-04-05T00:34:33.563 回答