TM90
TM90

Reputation: 700

Strange behavior of tcl comments?

I have the following tcl file:

proc test {} {
## proc test {} {
#      puts "test"
## }
    puts "Hallo"
}

Which does not produce an error.

If I now delete the closing braced in the comment I get an error

proc test {} {
## proc test {} {
#      puts "test"
## 
    puts "Hallo"
}

Why does the interpreter behave like this? Are parts of comments evaluated in some way?

Upvotes: 3

Views: 894

Answers (2)

Dinesh
Dinesh

Reputation: 16428

If a brace - that is to say, the character { - appears in a Tcl comment inside a proc, the Tcl parser will behave in a way that you may not expect. The # character is not a special preprocessor directive (as comments are in C/C++). In Tcl, comments act a lot like a command. If a command starts with the character #, then the rest of the line is ignored. When you define a proc in Tcl, you are actually running the proc command, and it expects three arguments: the name of the procedure, a list of procedure arguments and a procedure body. Both the argument list and the procedure body have to be properly formed strings, and they are usually quoted with braces. You can have nested quotes within these strings, but you can't have extra open braces or unbalanced quotation marks. So as far as the proc command is concerned, this is a perfectly valid declaration.

proc foo { args } {
      puts "executing procedure foo"
      # comment out this code block {
           foreach a $args {
                puts "argument: $a"
           }
      }
 }

Note that procedure body is a well formed Tcl string. All the nested braces balance. The proc command doesn't actually do anything with the procedure body. That happens later when you execute the procedure. When you execute the procedure foo, Tcl recognizes the # comment command, and ignores the rest of the characters on that line including the trailing open-brace. It then processes the foreach command, which expects three arguments, one of which is a multi-line string quoted by braces. It then attempts to process the closing brace as a command, and fails:

% foo test
 invalid command name "}"

You may have been trying to comment out a block of code, like this

 # comment out this block {
 proc foo {} {
      blah ; blah ; blah
 }
 }

but that doesn't work because of the unmatched braces in the comment. The most thorough way to comment out that block of code is to place a # at the beginning of each line. But that is a lot of work. Instead, if your block is well-formed, parsable, Tcl code, remove the code with an if or proc command, like this:

#  comment out this block using 'if'
 if 0 {
 proc foo {} {
      blah ; blah ; blah
 }
 }

or

#  comment out this block using 'proc'
 proc donteverrunme {} {
 proc foo {} {
      blah ; blah ; blah
 }
 }

Source : http://wiki.tcl.tk/462

Upvotes: 1

Donal Fellows
Donal Fellows

Reputation: 137687

Tcl's comments are real comments, but they're parsed at the same time as other parts of the syntax, such as braces. This means that when we parse your code, we've got to take into account the brace counting as well. Here's how the parser thinks:


“Ready to parse a command.”

proc test {} {

“Still parsing the command. Now looking for one closing brace.”

## proc test {} {

“Still parsing the command. Now looking for two closing braces.”

#      puts "test"

“Still parsing the command. Now looking for two closing braces.”

## 

“Still parsing the command. Now looking for two closing braces.”

    puts "Hallo"

“Still parsing the command. Now looking for two closing braces.”

}

“Still parsing the command. Now looking for one closing brace.”

“Oops! No more script but still looking for the end. Error time!”


The parser gets to the end and it's still looking for that closing brace. It only interprets the interior #s as the start of comments when the procedure is called and the procedure's body script is evaluated.

The upside to doing this is that you can use # for things other than comments as well, such as if you're embedding some C code inside your Tcl script, when the # starts a preprocessor directive.

Upvotes: 2

Related Questions