tcl 评论的奇怪行为?
Strange behavior of tcl comments?
我有以下 tcl 文件:
proc test {} {
## proc test {} {
# puts "test"
## }
puts "Hallo"
}
这不会产生错误。
如果我现在删除评论中的右括号,我会收到错误消息
proc test {} {
## proc test {} {
# puts "test"
##
puts "Hallo"
}
解释器为什么会这样?部分评论是否以某种方式评估?
如果大括号 - 也就是说,字符 {
- 出现在 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
}
}
Tcl 的注释是真正的注释,但它们与语法的其他部分(例如大括号)同时 被解析。这意味着当我们解析您的代码时,我们还必须考虑大括号计数。以下是解析器的想法:
“准备解析命令。”
proc test {} {
“还在解析指令。现在正在寻找一个右括号。”
## proc test {} {
“还在解析指令。现在正在寻找两个右大括号。”
# puts "test"
“还在解析指令。现在正在寻找两个右大括号。”
##
“还在解析指令。现在正在寻找两个右大括号。”
puts "Hallo"
“还在解析指令。现在正在寻找两个右大括号。”
}
“还在解析指令。现在正在寻找一个右括号。”
“糟糕!没有更多的剧本,但仍在寻找结局。错误时间!”
解析器已结束,它仍在寻找右大括号。当调用过程和计算过程的主体脚本时,它仅将内部 #
s 解释为注释的开始。
这样做的好处是您可以将 #
用于注释以外的其他内容,例如如果您在 Tcl 脚本中嵌入一些 C 代码,当 #
启动预处理器指令。
我有以下 tcl 文件:
proc test {} {
## proc test {} {
# puts "test"
## }
puts "Hallo"
}
这不会产生错误。
如果我现在删除评论中的右括号,我会收到错误消息
proc test {} {
## proc test {} {
# puts "test"
##
puts "Hallo"
}
解释器为什么会这样?部分评论是否以某种方式评估?
如果大括号 - 也就是说,字符 {
- 出现在 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
}
}
Tcl 的注释是真正的注释,但它们与语法的其他部分(例如大括号)同时 被解析。这意味着当我们解析您的代码时,我们还必须考虑大括号计数。以下是解析器的想法:
“准备解析命令。”
proc test {} {
“还在解析指令。现在正在寻找一个右括号。”
## proc test {} {
“还在解析指令。现在正在寻找两个右大括号。”
# puts "test"
“还在解析指令。现在正在寻找两个右大括号。”
##
“还在解析指令。现在正在寻找两个右大括号。”
puts "Hallo"
“还在解析指令。现在正在寻找两个右大括号。”
}
“还在解析指令。现在正在寻找一个右括号。”
“糟糕!没有更多的剧本,但仍在寻找结局。错误时间!”
解析器已结束,它仍在寻找右大括号。当调用过程和计算过程的主体脚本时,它仅将内部 #
s 解释为注释的开始。
这样做的好处是您可以将 #
用于注释以外的其他内容,例如如果您在 Tcl 脚本中嵌入一些 C 代码,当 #
启动预处理器指令。