1

This seems like really strange behavior for me in Tcl, or is this normal and I just don't understand how comments work?

This code runs just fine in Tcl:

#foreach corner {1 2} {
    #if { $a } {
#}

OK, nothing is actually running, but I get no error. But if I comment out the loop command, then the comment line inside the loop causes an error:

foreach corner {1 2} {
    #if { $a } {
}

The Tcl interpreter (tclsh) says:

missing close-brace: possible unbalanced brace in comment
    while executing
"foreach corner {1 2} {"
    (file "test.tcl" line 1)

Just for completeness, I should mention that when I delete that commented line, the error goes away.

Is that normal? Is there a better way to "comment out" lines while developing code? How can I make the interpreter completely ignore content in comments?

Chris
  • 37

1 Answers1

1

In Tcl, { ... } is not a code block – it's a string literal, the same kind of thing as "..." only with different "special character" rules (no variable expansion, etc).

For example, these are equivalent:

  • foreach corner {1 2 3} {puts $corner}
    
  • foreach corner "1 2 3" "puts \$corner"
    
  • set foo {puts $corner}
    foreach corner {1 2 3} $foo
    

Unlike traditional "-strings in which you have to escape every embedded quote (like "abc\"def"), one of the rules within a {}-string is that it can contain unquoted braces as long as they're balanced; i.e. a } doesn't necessarily terminate the string if the parser has seen some number of { before it. So you can have:

  • tclsh% set foo {one two {three four {five} six} seven}
    tclsh% lindex $foo 2
    three four {five} six
    
  • compared to:

    tclsh% set foo "one two \"three four \\\"five\\\" six\" seven"
    tclsh% lindex $foo 2
    three four "five" six
    

However, there is no rule in the parser about # comments within a string literal: that's just another regular character in the string.

  • tclsh% set foo {
               one {two}
               #three four
           }
    tclsh% lindex $foo 2
    #three
    

It would only become a comment later, when the string gets executed as the for-loop body (at which point its contents are parsed again), but right now the # means nothing to the outermost parser and every { and } in that line is still counted.

So if you have an unbalanced { within a {}-string, you might need to change it to \{ temporarily. (The backslash actually becomes part of the string value, but it won't hurt in this case.)

grawity
  • 501,077