'''This page is intended as to summarize some coding pitfalls I encountered in my early days of Tcl programming. As far as I know, this has not been issued anywhere else.''' Further contributions welcome -- [RJM]. While coding, it is important to realize which type of [argument] is '''expected''' by the various [Tcl] [command]s. This saves unnecessary quotings or even erroneous quotings. Also superfluous commands could be entered as in this example: if [expr {$a < 0}] {set a 0} Such silly sort of code lines may well occur when a beginner is getting confused about using the proper quoting, ''or when one thinks that only simple comparisons are allowed with if { } *''. The more appropriate method of writing the above is if {$a < 0} {set a 0} ;# the first 'if' argument already expects an expression While the original line may be valid Tcl code, it is not one of the Tcl [best practices]. This is the importance of learning Tcl [idioms] and having a collection of good Tcl examples from which to learn. To show a possible source of confusion, two commands are compared here: if {[command...] == xx} { for {[command...]} {..} { (The curly braces may be omitted in the second example because the enclosed text is one word). For a confused beginner, both lines seem to conform to a consistent syntax. Of course, the second case yields an error when the nested script does not return a valid command name. The beginner who is reading this should know that: * each command may have a "local" syntax of how to handle arguments. The [expr] command is one such command. * each argument may also be interpreted simply as tcl command/script, expression, or name of a variable. The first statement can be explained with a reference to [little language]. The latter statement will be looked at here briefly. * [if] expects an expression as its first argument, therefore there is no need to code the [expr] explicitly. * [for] expects a command/script as its first argument, therefore no [[]] necessary. The beginner must realize that the term "necessary" in the second example is incorrect. It suggests that where a command is expected, a [[]]-quoting would be harmless doubling. It must be emphasized that [[]] does '''substitution''' just as $ also substitution. To be precise: [[]] is not "quoting". See also [An Introduction to Tcl Scripting]. Further examples: * [time] expects a command as its first argument. time [[command...]] would substitute the script between [[]] upon Tcl parsing, and then the command [time] uses its result and treats this as a script. * [switch] is (at a first glance) confusing to C-programmers because they do not see the C ''case''. The well defined order and interpretation of the switch arguments as 'pattern-body' pairs enables proper operation of switch. * [incr] expects a variable name. Perhaps a bit silly to notice that no $ is "necessary". But it may help a beginner to understand why sometimes not to use $ and when not. BTW: $ would effectively result in double dereferencing. See also [dereferencing]. There are a couple of '''l*''' commands which are the same - and equally confusing. * [puts] expects nothing. Uh, this means that the argument is taken as processed by the parser. And send to the console in this form. That's why variable substitution in a string with white spaces must be enforced with enclosing "..". Other commands ''seem'' to substitute variables when { }-enclosed. But again: it depends on what the command '''expects'''. It may process the untouched argument with its own substitution (as with [expr]), or recursively call the interpreter (as is the case with all commands that treats an argument as script body). Look the [for]-command for an investigation in the endless loop pitfall when the ''condition'' argument has no { }. A bit confusing for beginners is the use of [list] in -command options of Tk widgets or as the ''script'' argument of [bind]. The usage of [[list .....]] in [[]] results in ''immediate'' command subsitution. Its result is treated as the effective command/script for the -command option or binding. It's all in the "Division of Responsibility" Parser <-> Command: Any substitution is carried out during Parsing. ---- * I have queried my sources for the character sequences '''if [[expr''' and '''if {[[expr'''. Indeed I used it when more complex expressions were defined. During this query, I surprisingly found these character sequences in several other sources, too. This includes the activestate distribution (mainly the second character sequence). I'd encourage the reader to check his/her own sources, too. -- [RJM] ---- [RS]: Note that the example above, if {$a < 0} {set a 0} could also be written in [expr]'s [little language]: set a [expr {$a<0? 0: $a}] Matter of taste, of course. ---- [Category Tutorial]