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
 }
 }

来源:http://wiki.tcl.tk/462

Tcl 的注释是真正的注释,但它们与语法的其他部分(例如大括号)同时 被解析。这意味着当我们解析您的代码时,我们还必须考虑大括号计数。以下是解析器的想法:


“准备解析命令。”

proc test {} {

“还在解析​​指令。现在正在寻找一个右括号。”

## proc test {} {

“还在解析​​指令。现在正在寻找两个右大括号。”

#      puts "test"

“还在解析​​指令。现在正在寻找两个右大括号。”

## 

“还在解析​​指令。现在正在寻找两个右大括号。”

    puts "Hallo"

“还在解析​​指令。现在正在寻找两个右大括号。”

}

“还在解析​​指令。现在正在寻找一个右括号。”

“糟糕!没有更多的剧本,但仍在寻找结局。错误时间!”


解析器已结束,它仍在寻找右大括号。当调用过程和计算过程的主体脚本时,它仅将内部 #s 解释为注释的开始。

这样做的好处是您可以将 # 用于注释以外的其他内容,例如如果您在 Tcl 脚本中嵌入一些 C 代码,当 #启动预处理器指令。