我有以下tcl文件:
proc test {} {
## proc test {} {
# puts "test"
## }
puts "Hallo"
}
哪个不会产生错误。
如果我现在删除评论中的括号,我会收到错误
proc test {} {
## proc test {} {
# puts "test"
##
puts "Hallo"
}
为什么解释器的行为如下?部分评论是否以某种方式进行评估?
答案 0 :(得分:1)
如果括号 - 也就是说,字符{
- 出现在proc中的Tcl注释中,则Tcl解析器将以您可能不期望的方式运行。
#
字符不是特殊的预处理程序指令(因为注释在C / C ++中)。在Tcl中,注释很像命令。如果命令以字符#
开头,则忽略该行的其余部分。
在Tcl中定义proc时,实际上是在运行proc命令,它需要三个参数:过程的名称,过程参数列表和过程体。参数列表和过程体都必须是正确形成的字符串,它们通常用括号引用。您可以在这些字符串中使用嵌套引号,但不能使用额外的开括号或不平衡的引号。因此,就proc命令而言,这是一个完全有效的声明。
proc foo { args } {
puts "executing procedure foo"
# comment out this code block {
foreach a $args {
puts "argument: $a"
}
}
}
请注意,过程体是一个格式良好的Tcl字符串。所有嵌套的括号都平衡。 proc
命令实际上对过程体没有任何作用。执行该过程后会发生这种情况。
当您执行foo过程时,Tcl会识别#
注释命令,并忽略该行上的其余字符,包括尾随的开括号。然后它处理foreach命令,该命令需要三个参数,其中一个参数是由大括号引用的多行字符串。然后它尝试将结束括号作为命令处理,并失败:
% foo test
invalid command name "}"
您可能一直试图注释掉一段代码,例如
# comment out this block {
proc foo {} {
blah ; blah ; blah
}
}
但由于评论中无法匹配的大括号,这不起作用。注释掉该代码块的最彻底的方法是在每行的开头放置#
。但这是很多工作。相反,如果您的块格式正确,可解析,Tcl代码,请使用if或proc命令删除代码,如下所示:
# comment out this block using 'if'
if 0 {
proc foo {} {
blah ; blah ; blah
}
}
或
# comment out this block using 'proc'
proc donteverrunme {} {
proc foo {} {
blah ; blah ; blah
}
}
答案 1 :(得分:1)
Tcl的评论是真实的评论,但它们与同时解析作为语法的其他部分,例如大括号。这意味着当我们解析你的代码时,我们也必须考虑括号计数。以下是解析器的思考方式:
“准备解析命令。”
proc test {} {
“仍在解析命令。现在正在寻找一个结束支撑。“
## proc test {} {
“仍在解析命令。现在正在寻找两个关闭的括号。“
# puts "test"
“仍在解析命令。现在正在寻找两个关闭的括号。“
##
“仍在解析命令。现在正在寻找两个关闭的括号。“
puts "Hallo"
“仍在解析命令。现在正在寻找两个关闭的括号。“
}
“仍在解析命令。现在正在寻找一个结束支撑。“
“糟糕!没有更多的脚本,但仍在寻找结束。错误时间!“
解析器到了最后,它仍在寻找那个结束括号。只有在调用过程并评估过程的主体脚本时,它才会将内部#
解释为注释的开头。
这样做的好处是,您可以将#
用于评论之外的其他内容,例如,如果您在Tcl脚本中嵌入了一些C代码,那么#
启动时预处理器指令。