我试图不在不同的开关块中重复相同的代码,并且无法弄清楚除了返回并退出程序之外如何打破开关脚本。
我的问题是,将开关包装在 while 循环中只是为了在需要时中断,这是一件可怕的事情吗?有更好的方法吗?
我花了一段时间,但我意识到中断是不必要的,因为可以在 catch 中设置变量并在其外部进行测试以确定何时运行 opt_2 下的其余代码(如下面的第二个代码示例所示);但休息一下会更清楚,特别是当实际代码比这个示例更复杂时。
谢谢你。
% proc SwitchBreak {condition valid} {
set ui_state 1
while { 1 } {
switch -- $condition {
opt_1 {
chan puts stdout opt_1
} opt_2 {
chan puts stdout opt_2
if { [info exists ui_state] && $ui_state == $valid } {
if { [catch { throw {Database Error} {Failed to Write} } result]} {
chan puts stdout "${result}. Rolled back"
set rv 1
set response {Operation Failed}
break
}
}
chan puts stdout {Opt_1 code to run only when\
no valid ui_state or valid state succeeds.}
set rv 0
set response {Successful write.}
} opt_3 {
chan puts stdout opt_3
} default {
chan puts stdout opt_4
}
}
break
}
chan puts stdout {Code after the switch.}
chan puts stdout "rv: $rv; response: $response"
}
% SwitchBreak opt_2 1
opt_2
Failed to Write. Rolled back
Code after the switch.
rv: 1; response: Operation Failed
% SwitchBreak opt_2 0
opt_2
Opt_1 code to run only when no valid ui_state or valid state succeeds.
Code after the switch.
rv: 0; response: Successful write.
无循环,无中断。
proc SwitchBreak {condition valid} {
set ui_state 1
switch -- $condition {
opt_1 {
chan puts stdout opt_1
} opt_2 {
chan puts stdout opt_2
set rv 0
if { [info exists ui_state] && $ui_state == $valid } {
if { [catch { throw {Database Error} {Failed to Write} } result]} {
chan puts stdout "${result}. Rolled back"
set rv 1
set response {Operation Failed}
}
}
if { $rv == 0 } {
chan puts stdout {Opt_1 code to run only when\
no valid ui_state or valid state succeeds.}
set response {Successful write.}
}
} opt_3 {
chan puts stdout opt_3
} default {
chan puts stdout opt_4
}
}
chan puts stdout {Code after the switch.}
chan puts stdout "rv: $rv; response: $response"
}
% %
% Switch opt_2 1
opt_2
Failed to Write. Rolled back
Code after the switch.
rv: 1; response: Operation Failed
% SwitchBreak opt_2 0
opt_2
Opt_1 code to run only when no valid ui_state or valid state succeeds.
Code after the switch.
rv: 0; response: Successful write.
虽然这是合法的,因为你可以编写它并且它会正确执行,但对我来说这看起来非常丑陋;一个简单的
if
...else
似乎能够表达意图,同时实际上更清晰。我什至可以说我希望这通常是真的。
# Just the bit inside the switch case
chan puts stdout opt_2
if {
[info exists ui_state] && $ui_state == $valid
&& [catch {
throw {Database Error} "Failed to Write"
} result]
} then {
chan puts stdout "${result}. Rolled back"
set rv 1
set response "Operation Failed"
} else {
chan puts stdout "Opt_1 code to run only when\
no valid ui_state or valid state succeeds."
set rv 0
set response "Successful write."
}
是否存在这样的情况:通过运行一次
while
来完成这个复杂的事情是最好的?我对此表示怀疑...但永远不要说永远。
运行一次
for
会稍微好一点,前提是将 break
放在增量子句中。这样,顶部就更清楚您在做什么。
或者您可以将
try
与 on break
子句一起使用。