是否可以从两个嵌套级别退出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,这比正确的语言构造更多的是hack。
答案 0 :(得分:2)
有可能在Tcl≥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
”。
答案 1 :(得分:2)
It's not possible to do it directly; the break
machinery doesn't have anything to trace up to anything other than the nearest looping context.
The easiest way of handling this is to use try
in 8.6 and a custom exception code (i.e., any value from 5 upwards).
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
}
}
Running that gives this output:
a=b; to show that this is not stopping the outermost loop 3 1 4 1 a=c; to show that this is not stopping the outermost loop 3 1 4 1
But it's pretty messy to do this; the best approach is typically to refactor your code so that you can just return
ordinarily to end the loop. Using apply
might make this easier:
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"
}
}
}}
}
The downside of using apply
is that it is a different variable context and has quite a bit more overhead (because of all the stack frame management). Still, the variable context thing can be worked around using upvar
if you're careful.