TCL中的if语句

时间:2012-06-29 11:06:00

标签: tcl

我对以下代码的tcl中的if语句有疑问:

if {(($number == 1)&&($name == "hello")) || (($number == 0)&&($name == "yes"))} {
    #do something here
}

上面的代码有效,但如果我这样写下来的话:

if {{$number == 1 && $name == "hello"} || {$number == 0&&$name == "yes"}} {
    #do something here
}

它抱怨$number预计是一个布尔值,为什么?第二个不是有效的表达吗?如何纠正?

4 个答案:

答案 0 :(得分:33)

大括号,{}和括号()

不可互换。

正式地,大括号(one exception)是一种引用,表示不对内容进行进一步的替换。在上面的第一种情况中,这意味着该参数被传递给if而没有替换,它将其作为表达式进行评估。表达式子语言对一般Tcl具有强烈类似的括号解释方案;它们表示没有进一步替换的字面值。

相比之下,括号在Tcl中大多不是特别的。例外是在数组元素的名称中(例如,$foo(bar)),在表达式子语言中(使用它们进行分组,如在整个编程中的数学表达式中)和正则表达式子语言(它们是不同类型的分组和其他一些事情)。使用括号 - 平衡或其他 - 作为Tcl中命令名称的一部分是完全合法的,但是你可能会让你的程序员抱怨你编写令人困惑的代码。

具体细节

在此特定情况下,此if的测试表达式:

if {{$number == 1 && $name == "hello"} || {$number == 0&&$name == "yes"}} {...}

被解析为:

blah#1 LOGICAL_OR blah#2

其中每个blah都是文字。不幸的是,blah#1(完全等于$number == 1 && $name == "hello")没有布尔解释。 (blah#2也没有,但我们从不打算考虑这一点。)这里的事情肯定是非常错误的!

最简单的解决方法是将那些伪造的大括号改回括号:

if {($number == 1 && $name == "hello") || ($number == 0&&$name == "yes")} {...}

我打赌这是你原本想要的。

警告:高级主题

但是,另一个解决方法是添加一些额外的内容:

if {[expr {$number == 1 && $name == "hello"}] || [expr {$number == 0&&$name == "yes"}]} {...}

这通常不是一个好主意 - 额外的批量没有额外的收益 - 但是在你尝试使用动态生成的表达式作为测试条件的情况下这是有意义的。 不要这样做 除非您真的确定需要这样做!我的意思是。这是一项非常先进的技术,您几乎不需要,而且通常有更好的方法来实现您的总体目标。如果您认为可能需要它,为了善良,请在此处询问SO,我们将尝试找到更好的方法;几乎总有一个可用。

答案 1 :(得分:1)

我认为您收到的错误消息并不意味着$number必须是布尔值(我收到消息expected boolean value but got "$number == 1 && $name == "hello"")。 这意味着字符串$number == 1 && $name == "hello"不是布尔值 - 这绝对是正确的。 如果在if表达式中使用花括号,则不会对这些字符串进行求值,而只是将其解释为字符串。

答案 2 :(得分:1)

简而言之:if使用特殊的“迷你语言”作为其条件脚本 - expr command同样理解。这在if manual page

中说明
  

if命令将expr1计算为表达式(与expr计算其参数的方式相同)。

与Tcl本身(类似LISP和/或类似Unix)相比,“expr迷你语言”在某种意义上更像“传统”,感觉就像是C。

答案 3 :(得分:1)

($number == 1)中,编号为1并进行比较.Ex:1==1此处输出为布尔值。 但是在{$number == 1 && $name == "hello"}中,由于花括号$number1进行比较,因此未分配$ number,因此获得的输出不是布尔值。