gyuunyuu
gyuunyuu

Reputation: 684

Use of brackets and space character in Tcl

I am still confused about the usage of the bracket i.e () [] and {} use in Tcl. I always get caught out using the wrong bracket, having missed brackets when it was required to use them or having used too many of them. Besides this, I am also getting confused by Tcl giving me different result depending on presence or absence of space character (in math expression) and also if I have used more than one space character in succession.

Can someone please give me the basic rules that I must keep in mind to get out of this mess. Brackets have always been simple to use in C and some other languages but here they are totally different.

Upvotes: 3

Views: 7854

Answers (2)

Donal Fellows
Donal Fellows

Reputation: 137567

At the level you're looking at, Tcl is very different to any other language you've ever worked with. The heart of Tcl is defined by the Tcl(n) manual page, which states that (among other things):

  • Whitespace separates words. Every command takes its arguments as a sequence of words. Newlines and semicolons separate command calls; they're totally equivalent, but good style is to use a newline instead of a semicolon.
  • {braces} are used mainly for quoting text so that it is passed to commands with no substitutions or word separation performed on it. They nest properly. Braces are also used after $ to do variable substitution in a few cases: that's a rare use.
  • "double quotes" are used for quoting text so that it is passed to commands with substitutions applied, but no word separation.
  • [brackets] are a command substitution. They are replaced with the result of running the script inside the bracket. The script is usually a single command.
  • (parentheses) only have one base language use: for (associative) array elements. Thus, $a(b) is a variable substitution that will use the value of the b element in the a array.

The rest of what people call Tcl is really just a standard library, a set of commands to get you started. Some are fundamental. For example:

  • if is a conditional command, evaluating a branch (a script) if a condition is true. In order for this to be meaningful, the branch has to be not evaluated until the condition has been evaluated and tested; that pretty much requires putting it in braces.

  • while is a looping command, and not only do you want to brace its body (that's probably going to be evaluated over and over) but you also want to put the condition expression in braces as well as you definitely want that to be reevaluated each time round the loop.

  • proc is a command that makes your own custom commands. The body of the procedure definitely is something you want to evaluate later; it goes in braces.

  • expr is a general expression evaluation command. Under all normal circumstances, you'll want to put its expression in braces so that the code can be compiled and won't have double substitution problems. Note that expressions often make heavy use of parentheses: they have additional meanings in expression syntax. In particular, apart from being array element lookups, they're also used for function calls and grouping.

    Note that if and while also use that same expression evaluation engine. They just use the result of the expression to decide what to do.

Scoping is a matter for commands to decide. The usual commands for dealing with introducing a scope are proc and namespace eval. This is nothing like C, C++, Java, C#, or Javascript; they have different rules. Variables are local to their procedure unless you explicitly say otherwise.


The community practice is to do calls like this:

if { $foo(bar) > (17 + $grill) * 7 } {
    # This is a comment; it lasts to the end of the line
    puts "the foobar $foo(bar) is too large"
    set foo(bar) [ComputeSmallerValue $grill]
}

That is, barewords (if and puts) are unquoted, expressions and inner scripts are brace-quoted, parentheses are used where meaningful but most for arrays and expressions, whitespace separates all words, inner scripts are indented (usually by 4) for clarity (it doesn't have semantic meaning, but it sure helps with reading), and “blocks” use egyptian braces so that you don't have to add backslashes all over the place.

You don't have to follow these rules (they're guidelines, not the law) but they make your life easier if you do. Sometimes you do need to break the rules, but then you should know to be careful.

Upvotes: 8

Brad Lanam
Brad Lanam

Reputation: 5723

You cannot compare Tcl to C. In C, {} defines scope. In Tcl, {} is a grouping operator.

In Tcl, {} may group a string:

 {hello world}

Or a list:

 {a b c d e f g h}

Or a script:

 {
 puts -nonewline {hello }
 puts world\n
 }

Every command is simply a series of groups (which may be a word, a list, an expression or a script):

 {if} {true} { puts "hello\n" }

Of course, you don't need to put braces around every word, but you do need braces to enclose a script:

 if true { puts hello\n }

Generally, for the if statement, not bracing the expression is a bad idea, so this is better:

 if { true } { puts hello\n }

This simple rule creates Tcl's remarkably simple syntax. Every command is simply a series of groups, whether a word, an expression, a list or script:

 if expr script
 while expr script
 proc name argument-list script
 puts string
 for initialization condition nextloop script

The one important thing to remember is whenever an expression is wanted, it should be enclosed within braces in order to prevent early substitution. e.g.:

 set i 0
 while { $i < 10 } {
    incr i
 }

The square brackets, [], are replaced with the output of a command enclosed by the square brackets:

 set output [expr {2**5}]

Parentheses are used within expressions as usual:

 set output [expr {(2**5)+2}]

And for arrays:

 set i 0
 while { $i < 5 } {
   set output($i) [expr {2**$i}]
   incr i
 }
 parray output

Upvotes: 2

Related Questions