'''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. * [if] (second look) is at a first glance possibly confusing to experienced tcl programmers when they would encounter the command the first time. Corresponding to [switch] one should expect a chain of arguments: basically ''expr, if'' clause, ''else'' clause. A little bit loss of consequent Tcl habits arises when the ''elseif'' clause comes into focus. A "keyword" is required here in order to let the [if] command processor recognize a repeat of ''expr'' etc. '''arguments'''. Besides this "keyword", [if] allows the usage of ''then'' and ''else'' as dummy words to serve code readability. See the manpage referenced to in the [if] page. * [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 at the [for]-command for an investigation in the endless loop pitfall when the ''condition'' argument has no { }. [LV] Okay, I think what is going on here is this. Hopefully one of the [guru]s will correct me if I am mistaken. There are several steps to code being processed. When the interpreter reads a line in, it processes the lines based on the tcl syntax. If the line, as coded, permits variables to be substituted, they are. Then the command is invoked with the resulting arguments. Some of the Tcl commands because of their nature, expect pieces of tcl code of one type or another as one of their arguments. In these cases, the tcl command itself then performs an [eval] of the appropriate argument. This is likely to be the source of the confusion that the originator of this page references. Someone new to Tcl may a) not realize that which commands perform the extra eval's and/or b) may not realize the implications of the extra eval. ---- 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. [RJM]: Another example pair also shows how argument expectations influence quoting: set path [expr {$b=="" ? [pwd]: [file join $b]}] set path [if {$b==""} pwd else {file join $b}] Note that [if] returns the result of the executed command (remark: I also added a second [if] entry in the bulleted list of commands above). ---- [Category Tutorial]