我发现了一个非常奇怪的bug(?),它花了我几乎一整天才在实际应用中找到它.在代码中有一个elseif被注释掉的块,它导致执行代码(我认为)无法执行.
我简化了重现这个奇怪的tcl行为的测试用例.
proc funnyProc {value} {
if {$value} {
return "TRUE"
# } elseif {[puts "COMMENT :)"] == ""} {
# return "COMMENT"
} else {
return "FALSE"
}
return "IT'S IMPOSSIBLE!!!"
}
puts [funnyProc false]
Run Code Online (Sandbox Code Playgroud)
您认为该计划将产生什么?
puts注释行被执行.任何编程语言POV都是不可能的.if {...} {return} else {return}被执行.true/false逻辑是不可能的.我知道tcl-comment的行为类似于带有名称的命令,#并且在EOL之前使用所有参数.并且tcl解析器不喜欢注释中的不平衡花括号.但这个案例不符合我的理解.
也许我错过了重要的事情?如何正确地注释掉这些elseif块,所以不要有这些奇怪的副作用?
这是因为#当Tcl正在寻找命令的开始时,它只是一个注释,并且它第一次看到它(解析时if),它正在寻找a }以便关闭之前的命令{.这是Tcl解析规则的结果; if只是一个命令,而不是一个特殊的构造.
欧内斯特注意到的效果是因为它增加了该行上大括号的嵌套级别,这使得它成为从行尾到if {$value} {行开头的参数的一部分} else {.然后#在if评估脚本时变得特殊.(好吧,除了它编译的所有字节码,但这是一个实现细节:观察到的语义是相同的,除了一些非常讨厌的边缘情况.)