我正在尝试在 tcl 中实现一个自定义的 if 过程,我们称之为 if+。对于初学者来说,我希望 if+ 能够准确地执行 if 正在执行的操作。
到目前为止我所拥有的:
proc if+ {expr1 body1 args} {
if {[uplevel 1 [list expr $expr1]]} {
uplevel 1 $body1
return
}
for {set i 0} {$i < [llength $args]} {incr i 3} {
if {[lindex $args $i] eq "else"} {
uplevel 1 [lindex $args [expr $i+1]]
return
} elseif {[lindex $args $i] eq "elseif"} {
if {[uplevel 1 [list expr [lindex $args [expr $i+1]]]]} {
uplevel 1 [lindex $args [expr $i+2]]
return
}
}
}
}
它已经工作得很好,但有一个例外:当您将 return 语句放入一个 if+ 块的主体中时,它仅从 if+ 返回,而不是从其周围的过程返回。这可以从这个简单的例子中看出:
proc p {} {
if+ true {
puts A
return
}
puts B
}
这个过程的输出是'A'和'B',而使用if而不是if+,它只是'A'。如何修改我的 if+ 使其与 if 完全相同?
try
捕获 return
并将 1 添加到其 level,以便它从调用堆栈中的正确函数返回:
proc if+ {expr1 body1 args} {
try {
if {[uplevel 1 [list expr $expr1]]} {
uplevel 1 $body1
break ;# instead of return
}
for {set i 0} {$i < [llength $args]} {incr i 3} {
if {[lindex $args $i] eq "else"} {
uplevel 1 [lindex $args $i+1]
break
} elseif {[lindex $args $i] eq "elseif"} {
if {[uplevel 1 [list expr [lindex $args $i+1]]]} {
uplevel 1 [lindex $args $i+2]
break
}
}
}
} on return {val options} {
dict incr options -level
return -options $options $val
}
}
另请注意删除了
expr
参数中的 lindex
调用;在这种情况下不需要它们,因为 lindex
本身可以进行数学计算,但如果您确实使用 expr
来做这样的事情,支撑您的 expr
-essions。