1.6 On the Tcl Language
As a programming language, Tcl is defined quite differently from most other languages. Most languages have a grammar that defines the entire language. For example, consider the following statement in C:
while (val>0) { result *= val; val -= 1; }
The grammar for C defines the structure of this statement in terms of a reserved word while, an expression, and a substatement to execute repeatedly until the expression evaluates to zero. The C grammar defines both the overall structure of the while statement and the internal structure of its expression and substatement.
In Tcl no fixed grammar explains the entire language. Instead, Tcl is defined by an interpreter that parses single Tcl commands, plus a collection of procedures that execute individual commands. The interpreter and its substitution rules are fixed, but new commands can be defined at any time and existing commands can be replaced. Features such as control flow, procedures, and expressions are implemented as commands; they are not understood directly by the Tcl interpreter. For example, consider the Tcl command that is equivalent to the preceding while loop:
while {$val>0} { set result [expr $result*$val] incr val -1 }
When this command is evaluated, the Tcl interpreter knows nothing about the command except that it has three words, the first of which is a command name. The Tcl interpreter has no idea that the first argument to while is an expression and the second is a Tcl script. Once the command has been parsed, the Tcl interpreter passes the words of the command to while, which treats its first argument as an expression and the second as a Tcl script. If the expression evaluates to nonzero, while passes its second argument back to the Tcl interpreter for evaluation. At this point the interpreter treats the contents of the argument as a script (i.e., it performs command and variable substitutions and invokes the expr, set, and incr commands).
Now consider the following command:
set {$val>0} { set result [expr $result*$val] incr val -1 }
As far as the Tcl interpreter is concerned, the set command is identical to the while command except that it has a different command name. The interpreter handles this command in exactly the same way as the while command, except that it invokes a different procedure to execute the command. The set command treats its first argument as a variable name and its second argument as a new value for that variable, so it will set a variable with the rather unusual name of $val>0.
The most common mistake made by new Tcl users is to try to understand Tcl scripts in terms of a grammar; this leads people to expect much more sophisticated behavior from the interpreter than actually exists. For example, a C programmer using Tcl for the first time might think that the first pair of braces in the while command serves a different purpose from the second pair. In reality, there is no difference. In each case the braces are present so that the Tcl interpreter passes the characters between the braces to the command without performing any substitutions.
Thus the entire Tcl "language" consists of about a dozen simple rules for parsing arguments and performing substitutions. The actual behavior of a Tcl script is determined by the commands executed. The commands determine whether to treat an argument as a literal value, the name of a variable, a code block to execute, and so on. An interesting consequence of this is that a script can define commands implementing entirely new control structures, which is a feature not available in most other languages.