Tcl is a language of values. By the time a command gets to see its arguments, Tcl has already performed its [Dodekalogue%|%various substitutions%|%] on those arguments. Many commands perform their own substitutions on their arguments (the arguments they receive from the Tcl interpreter, which has already processed them for its own purposes), and this is what "double substitution" usually refers to. The quintessential example is the [[[expr]]] command, but it is not the only one. Here are some other examples: [[[expr]]]: interprets `$` as variable substitution, `[` as command substition, etc. [[[set]]]: interpets parenthesis as array element access [[[list]]]: interprets `\` as backslash substitution, `"` and `{` as a grouping operators. Actally, this is also true of all the list commands [[[eval]]]: interprets its arguments as entire Tcl scripts [[[regexp]]] and [[[regsub]]]: interpret regular expression syntax in all its glory [[[string match]]]: interprets `*`, `?`, `[`, and `\` Each of these commands can be thought of as a separate interpreter that implements its own mini-language. Anywhere a command is performing some sort of interpretation on some of the characters in its arguments, there are two layers of interpretation happening: Tcl performs its substitutions on command arguments first, and then the command may perform its own substitutions. Those just learning Tcl may be caught off-guard by this double subsitution, but it is not considered a bug, and with practice, it comes to feel like a natural part of the design of Tcl. To avoid [Injection Attack%|%injection attacks%|%], it is important to understand and be aware of command substitution behaviour. The reason [[[expr]]] arguments should [brace your expr-essions%|%always be braced] is that it avoids the first layer of substitution by the Tcl script interpreter. The same is true for the first argument to '''[if]''' and '''[while]'''. This is mentioned on the [Tcl Style Guide] page and is discussed a bit on [A Question of Style]. Use [TclPro]'s syntax checker (named ''[procheck]'') to check for mistakes. As [Cameron Laird] says, "Tcl's syntax is small enough to fit in the working memory of a typical human." However, the main work of understanding double substitution lies in understanding how each command you choose to use operates, and how it interprets its arguments. The [dodekalogue%|%standard rules of Tcl%|%] describe the syntax of Tcl, and the documentation for commands such as [[[expr]]], [[[if]]], and [[[while]]] describe how each of those commands interpret, and possibly perform substitutions on their arguments. Rule 2 says that a Tcl command is evaluated in two steps. First, the Tcl interpreter breaks the command into words and performs substitutions. Then the interpreter uses the first word as a command name, calls the command, and passes the rest of the words to the command as arguments. Rule 5 says that substitutions are not performed on words surrounded by braces. That's a good thing because the expression parser (on the [expr] man page) will perform its own substitutions. You are getting bitten by unbraced expressions performing double-substitution. Here is an example of a common mistake: ====== #warning: bad code ahead! set myString "hello" if $myString=={} {puts "empty string"} ====== By the time the [[[if]]] command sees its first argument, it looks like this: ====== hello=={} ====== In expressions, strings must be quoted, and now `hello` is not, so an error occurs. `hello` was quoted for Tcl when it performed its substitutions, but it then was not quoted for [[[expr]]] (via [[[if]]]), which, requires that strings be enclosed in double quotes or braces. Note also that that the Tcl did not substitute away the curly brackets after `==`, since brace and double-quote grouping only happens when a brace or double quote occur at the beginning of a word ====== #warning: bad code ahead! set myString "hello there" if $myString=={} {puts "empty string"} ====== In this case, [[[expr]]] gets the following value for its argument: ====== hello there=={} ====== which is even more of an error because now [[[expr]]] can't make sense of the number of arguments *** a complex example *** In the following example, there are many issuses: ====== #warning: bad code ahead! set myString "This is a string with \[special characters\}" if $myString=={} {puts "empty string"} ====== [[[expr]]] (once again, via [[[if]]]), sees the following value: ====== This is a string with [special characters}== ====== there are seven arguments, which makes no sense to [[[expr]]]: * a left square bracket signaling command substitution, but no corresponding closing bracket * a right curly bracket signaling the end of a grouping operation, but no corresponding left curly bracket * seven arguments with only one opertor to be found, which syntactically makes no sense to [[[expr]]] The moral of the story, of course, is to prevent the Tcl substitutions with curly braces: ====== if {$myString==""} {puts "empty string"} ====== Now, [[[expr]]] sees something more reasonable: ====== This\ is\ a\ string\ with\ \[special\ characters\}=={} ====== In summary, use braces on '''if''' and '''while''' and '''expr''' expressions. Use [ProCheck] to make sure you haven't missed any. ---- [KBK] - Another point that should be made is that braced expressions on [[if]], [[while]] and [[expr]] aren't just safer, they're also much, much faster. Unbraced ones have to be parsed at run time; braced ones can be compiled down to very tight [bytecode] sequences. <> String Processing