If statement 完全被这个TCL代码迷惑了

If statement 完全被这个TCL代码迷惑了,if-statement,while-loop,tcl,If Statement,While Loop,Tcl,我刚刚开始在TCL中编写代码,有以下while循环代码: set x 0 while "$x < 5" { set x [expr {$x + 1}] if {$x > 7} break if "$x > 3" continue puts "x is $x" } puts "exited second loop with X equal to $x" 这让我很困惑。我很好奇,“$x>3”的计算结果是否会像[expr{“$x>3”}]或(这是一

我刚刚开始在TCL中编写代码,有以下while循环代码:

set x 0
while "$x < 5" {
    set x [expr {$x + 1}]
    if {$x > 7} break
    if "$x > 3" continue
    puts "x is $x"
}

puts "exited second loop with X equal to $x"
这让我很困惑。我很好奇,
“$x>3”
的计算结果是否会像
[expr{“$x>3”}]
或(这是一个字符串,因为它本身就是一个字符串,所以它是真的。)

它是如何工作的?把机械师给我。巨大的偏头痛正在试图弄明白这一点。

文件说:

if expr1 ?then? body1 elseif expr2 ?then? body2 elseif ... ?else? ?bodyN?
if命令将expr1计算为表达式(与expr计算其参数的方式相同)

这意味着
$x>3
使用
expr
进行评估

我注意到您在
while
if
条件中使用了双引号而不是大括号。请使用大括号,如中所示:

while {$x < 5} { ... }
文件说:

if expr1 ?then? body1 elseif expr2 ?then? body2 elseif ... ?else? ?bodyN?
if命令将expr1计算为表达式(与expr计算其参数的方式相同)

这意味着
$x>3
使用
expr
进行评估

我注意到您在
while
if
条件中使用了双引号而不是大括号。请使用大括号,如中所示:

while {$x < 5} { ... }

Tcl有一个非常简单的评估模型。它总是按照它所看到的东西来评价事物;如果一个单词在大括号中,它将不被替换,但在其他情况下,它应用了
$
[…]
(和
\
,但不使用这些)替换;
“…”
只是将一组字符组合成一个单词(即,它覆盖了通常的空格分隔规则)。组装好单词后,它将它们发送到命令实现(从第一个单词开始查找)以执行。就这样

建议您始终用括号括住表达式,因为这样可以避免混淆(并使Tcl能够编译代码)


适用于你的情况 没有替代品。三个字
set
0
写入变量
x

while "$x < 5" {
    set x [expr {$x + 1}]
    if {$x > 7} break
    if "$x > 3" continue
    puts "x is $x"
}
if {$x > 7} break
我们用
expr
(计算表达式
$x+1
,生成
1
)替换了一个命令,这是整个第三个单词。最终结果是
set
将值
1
放入变量
x

while "$x < 5" {
    set x [expr {$x + 1}]
    if {$x > 7} break
    if "$x > 3" continue
    puts "x is $x"
}
if {$x > 7} break
嗯,
如果
$x>7
的计算结果为true(不为true),则对脚本进行计算
中断
。不计算脚本的值

if "$x > 3" continue
puts "x is $x"
如果
1>3
(有双引号,请立即替换)评估脚本
继续
。不计算脚本的值

if "$x > 3" continue
puts "x is $x"
x为1
传递到
put
,后者将打印它

循环,第二次/第三次迭代 与上面相同,除了使用
2
/
3
而不是
1

循环,第四次迭代

这一次,当我们到达

if "$x > 3" continue
我们最终得到表达式
4>3
,这是真的,因此我们计算“body”脚本
continue
。这是一个生成continue异常的简单命令。
while
捕捉到这一点,然后返回并再次测试循环条件(并开始第五次迭代)。净效果是跳过循环体末尾的
put

迭代5,6,7 这些与迭代4非常相似

请注意,
“…”
仅在达到它们时才进行计算。这意味着,对于循环中的循环,每次循环都会对它们进行评估/替换。但是,
while
的循环条件不会在每次调用命令之前进行替换,因此不会重新替换。(这有点让人困惑,因为它们还支持类似Tcl的语法
$
[…]
“…”
,但它们在形式上是一种独立的语言,有一个独立的解析器。)

迭代8 顶行的
set
/
expr
x
设置为
8
。当它到达下一行时:

if {$x > 7} break
表达式将求值为true(因为变量
x
的内容大于
7
),并且将求值
break
。这将生成中断异常,导致
while
完成

搞不清状况 现在,我们又在外面处理最后一个命令:

puts "exited second loop with X equal to $x"
您需要对这个进行演练吗


看看到底发生了什么 您可以使用来自的命令执行跟踪代码的改编,以准确地了解发生了什么。只需将代码放入一个过程中,应用跟踪程序,并启动跟踪程序,就可以准确地看到发生了什么,每一个细节。(好吧,只有替换的结果,但你可能可以从中找出答案。)

在这里,我将向您展示:

proc YourCode {} {
    set x 0
    while "$x < 5" {
        set x [expr {$x + 1}]
        if {$x > 7} break
        if "$x > 3" continue
        puts "x is $x"
    }

    puts "exited second loop with X equal to $x"
}
trace add execution YourCode {enterstep leavestep} showCalls
proc showCalls {cmd args} {
    switch [lindex $args end] {
        enterstep {
            incr counter
            puts >>>$cmd
        }
        leavestep {
            lassign $args code result
            puts "<<<$cmd <<<$code,$result<<<"
        }
    }
}

YourCode
proc YourCode{}{
集x0
而“$x<5”{
集合x[expr{$x+1}]
如果{$x>7}中断
如果“$x>3”继续
把“x是$x”
}
放置“退出的第二个循环,X等于$X”
}
跟踪添加执行代码{enterstep leavestep}showCalls
proc showCalls{cmd args}{
开关[lindex$args end]{
进阶{
递增计数器
放入>>$cmd
}
叶阶{
lassign$args代码结果
将“3”放在继续位置
把“x是$x”
}
>>>expr{$x+1}

Tcl有一个非常简单的评估模型。它总是按照它所看到的东西进行评估;如果一个单词在大括号中,它就没有被替换,但是它有
$
[…]
(和
\
,但你没有使用这些)替换;
“…
只是将一组字符组合成一个单词(也就是说,它覆盖了通常的空格分隔规则)。一旦组合好单词,它就会将它们发送到命令实现(从第一个单词开始查找)以执行。就是这样

建议您始终用括号括住表达式,因为这样可以避免混淆(并使Tcl能够编译代码)


适用于你的情况 没有替换。三个字。
set<