是否可以在1个命令中从两个嵌套级别退出?也就是说,假设我有这个代码:
foreach l { 1 2 3 4 } {
foreach k { 3 4 5 6 } {
if { $k > 4 } {
break2
} else {
puts "$k $l"
}
}
我希望看到的输出是:
1 3
1 4
问题是,如何对break2进行编码(如果可能的话)
我不知道任何语言中有这样的"功能",除了将其封装在proc中,并使用return来停止proc,这更像是一种破解,而不是正确的语言构造
谢谢。
不可能直接执行;CCD_ 1机器除了最近的循环上下文之外没有任何东西可以追踪到。
处理此问题的最简单方法是在8.6中使用try
和自定义异常代码(即,从5开始的任何值)。
foreach a {b c} {
puts "a=$a; to show that this is not stopping the outermost loop"
try {
foreach l { 1 2 3 4 } {
foreach k { 3 4 5 6 } {
if { $k > 4 } {
# Generating a custom exception code is a bit messy
return -level 0 -code 5
}
puts "$k $l"
}
}
} on 5 {} {
# Do nothing here; we've broken out
}
}
运行时给出以下输出:
a=b;以表明这并没有停止最外层的循环3 14 1a=c;以表明这并没有停止最外层的循环3 14 1
但这样做很麻烦;最好的方法通常是重构代码,这样您就可以正常地使用return
来结束循环。使用apply
可能会让这变得更容易:
foreach a {b c} {
puts "a=$a; to show that this is not stopping the outermost loop"
apply {{} {
foreach l { 1 2 3 4 } {
foreach k { 3 4 5 6 } {
if { $k > 4 } {
return
}
puts "$k $l"
}
}
}}
}
使用apply
的缺点是它是一个不同的变量上下文,并且有相当多的开销(因为所有的堆栈帧管理)。不过,如果你小心的话,可以使用upvar
来解决可变上下文的问题。
这在Tcl&ge中是可能的;8.5:
foreach l { 1 2 3 4 } {
foreach k { 3 4 5 6 } {
if {$k > 4} {
return -code break -level 2
} else {
puts "$k $l"
}
}
}
return -code break -level 2
的工作原理类似于"使封闭命令在堆栈上两级返回,就好像它调用了break
一样"。
return
命令手册页面。