Version 139 of Tcl Advocacy

Updated 2013-03-01 18:46:55 by pooryorick

originally by slebetman, for those who are Learning Tcl

The Zen of the Tcl

Tcl is probably not like any other programming language you are likely to encounter. The best way to approach Tcl is to think of the command line, be it DOS or bash or tcsh or Cisco's telnet shell.

All statements in Tcl work just like running a program from the command line. That is, the first word is a command and the following words are parameters to that command. For example, in DOS to list the contents of a directory you would type:

dir c:\path\to\folder

in Tcl you would write:

glob /path/to/folder/*

Just like in DOS, the first word of a Tcl statement is always a command. Simple isn't it?

The glob command is just one of the commands available in Tcl. Another useful command is the puts command. It simply prints things out on the screen. Try it:

puts "Hello World!"

You may think of it as put string but I usually think of it as the plural of put (since it can output more than one character).

Notice that puts is similar to the echo command in DOS and Unix shells. Again, this shows how simple Tcl is.

Any Comments?..

In Tcl any command (first word in a statement) that begins with the # character is ignored. This is how one inserts comments. Comments are nice since they allow you do document things which may not be obvious in your code.

#This is a comment
# the Tcl interpreter will ignore comments so you can say whatever you like ;-)

Variables and Values

In all programming languages, you use variables to store values. Some languages prevent you from storing different kinds of values into different kinds of variables. But we'll have none of that here. In Tcl a variable can hold anything (even complete programs if you want to). Variables will even hold your hand:

set my_variable "your hand"

well.. maybe not your hand, but the code above stores the string "your hand" into a variable called my_variable. The set command is used to assign values to variables. It can also be used to get the value contained by the variable:

#assign value:
set new_var 100
#get value and print it on screen
puts [set new_var]

Programmers usually don't like typing too much. So Tcl provides a kind of shortcut to get the value of variables without using the set command. Simply add a $ sign in front of the variable to get its value:

#another way to get value of variables
puts $new_var

#you can even assign values of other variables to a varaible:
set my_variable $new_var

Notice that when one uses the set command on a variable, one uses the variable without the $ sign. This is because the $ sign is not used to signify a variable like in Perl but is merely a shortcut for getting its value.

Just for fun, what do you think happens in the following code?

set foo "this is cool"
set bar foo
puts [set $bar]

In the first statement, the variable foo is set to hold the string "this is cool". The variable bar is then set to the word "foo". Notice that there is no $ sign in front of foo. This means that bar is not assigned the value of foo but just simply the word foo.

The interesting part is the third statement. The set command is used to get the value of $bar. Since bar itself contains the word foo, what happens is we get the value contained in the value of bar. Confused?

Let's examine the third line step by step. The $ sign is a shortcut to get the value of a variable. So $bar returns the word foo. The set command then gets the value of foo and returns the string "this is cool". The third line can also be written as:

puts [set [set bar]]

but writing $$bar does not work. This is because $$ is not something Tcl understands.

Groupings

There are several things I did not explain in the examples above. One of which is the use of the double quotes ("). I know what you're thinking: I know that, it's a string. Correct..., but not quite. You see, in Tcl, everything is a string until it needs to be something else. Even 200 is a string until you try to add 1 to it. What the quotes represent in Tcl is grouping - a far simpler and powerful concept.

Let's take a look at the set command. It accepts either one or two parameters. If there are two parameters then the second parameter is a value to be assigned to the first parameter (which is a variable name). What if our string consists of more than one word? Trying to do:

#warning, bad code ahead!
set foo this is cool

will result in

error: wrong # args: should be "set varName ?newValue?"

why? because we are given set four parameters, instead of two. we should write:

set foo "this is cool"

So Tcl provides mechanisms to group words together. In the earlier example, foo is the first parameter and "this is cool" is the second, grouped by the quotes.

Tcl provides two ways to group things: the double quotes " and curly braces {}. The above example would also work with:

set foo {this is cool}

What's the difference? Why two kinds of groupings? Well, things grouped with the double quotes will go through substitution. Things grouped with braces will be left alone. You're saying what??.. Lets see an example:

set foo 100
puts {example1 $foo}
puts "example2 $foo"

The above code will print out:

example1 $foo
example2 100

that's because the first puts statement is left alone while the second one is substituted.

Substitution

We have seen one kind of substitution already. That is the $ shortcut. This is called variable substitution because it replaces the variable with its value. Substitutions are what makes Tcl tick. It is a powerful, flexible and simple concept. There are three kinds of substitutions in Tcl: variable substitutions, command substitutions and backslash substitutions.

We have already seen variable substitution and it is explained above. It simply substitutes the value of the variable in place of the variable itself when a $ sign is added in front of the variable.

Command substitution is similar in that it substitutes the result of a command in place of the command. We have in fact already seen this above, but I did not explain it. Basically a statement between square brackets [ ] is treated as a command and is evaluated. The result is then substituted in its place. For example:

set bat "a list of files in the current directory: [glob *]"

The glob command is evaluated, and its result is inserted into the string which is then assigned to the variable bat. We have seen similar syntax in the various set and puts examples above.

Backslash substitution is very similar to C/C++. The following are backslash substitutions understood by Tcl:

  • \a Audible alert (bell) (0x7).
  • \b Backspace (0x8).
  • \f Form feed (0xc).
  • \n Newline, LF (0xa).
  • \r Carriage-return, CR (0xd).
  • \t Tab (0x9).
  • \v Vertical tab (0xb).

Also, if a \ is followed by up to 3 digits of numbers, than it is treated as an octal value for a character and the actual character is then substituted in its place.

Any other character following a \ is replace with itself. This is an 'escape' mechanism that enables you to include special characters:

puts "This is how you print the double quote (\")"

In addition, if a backslash \ appears at the end of a line, then that line continues on to the next line:

puts \
  "Continued from the line above"

This is to allow a long line of code to be split into multiple lines if you run out of space in your text editor.

See also: http://www.tcl.tk/man/tcl8.4/TclCmd/Tcl.htm


What is a list?

In Tcl, everything is a string. But what is a list? It is basically, a string in which elements are separated by spaces.

set a "A B C"
lindex $a 0

The above commands return :

A B C
A

lindex returns a list element, located at a given index. Indices start at 0.

set a {A B C}
lindex $a 1

returns "B".

-- Sarnold 2005/11/27

DKF: But it's not just that, since you can put lists inside lists, like this:

set a "A {B C} D"
lindex $a 1

returning:

A {B C} D
B C

Because of this sort of thing, you need to remember that not all strings are lists. Instead, use the split command to convert a string into a list of words.


JM: slebetman, I would like to participate in this page, I can suggest an idea that I think fits, then if you agree I can insert the text where I think it belongs, so I don't mess original idea of this page.

example:

for the "any comments?" section, we can include that, a common, alternative way to insert comments in tcl (and I think not just in tcl) is by means of:

if {0}  {
    these are the comments
}

which is really code that is never executed.

slebetman: I'd wait until we introduce the 'if' command. I know if is obvious to anyone who is used to programming in any language. But I want to impress the essence of Tcl to newbies. Mixing syntax and command is not good in my view.

But thanks for your support. Please edit away any mistakes that you find here. But please refrain from commenting in-line. Comment at the bottom. In-line comments in the text itself is to be considered transient and may be edited away once corrections are made.

Also, if you find ways to re-phrase sentences and paragraphs in a more 'friendly' manner, please do so (in-line comments may be appropriate in this case if there is no consensus yet). I want to keep the tone of this introduction fun, friendly and informal, sort of like for-dummies, maybe even more fun. Humor is very much encouraged but not at the expense clarity: fun, not flippant.

Anyway, I think the syntax rules are covered. Feel free to start describing commands like if, proc etc. Don't worry about which comes before/after which. We can always edit and re-arrange chapters later.

Lars H 2005-11-28: Well, there's no mention of \x and \u substitution. I find \u interesting to mention, since it points to the fact that Tcl is not restricted to 8-bit characters, which however many other languages are.

slebetman: Good catch. Missed that. I'll be adding it later when I have time. Or you are free to do it yourself.

escargo 2004-11-28: I don't like spoiling the fun, but I think it's worthwhile mentioning some of the "gotchas" of Tcl. For example, that comments require balanced delimiters, that commands that take similar parameters don't necessarily take identical parameters (that is, some things can be more irregular than other languages because there isn't an overarching grammar that enforces regularity).

AET 2005-11-29: I agree, but there are many places where such information interrupts the learning flow. A simple DO and DONT list is less confusing for a beginner. And please, PLEASE resist the temptation (that so many have fallen to) to describe a new subject in terms of Here's some code that doesn't work, and here's why . . . A beginner needs to see and absorb simple, clear and above all CORRECT code. Please also keep debate of finer points of style, completeness, unusual exceptions etc. to other pages.

slebetman: I agree with AET. I intend to give new users the 'feel' of Tcl which I and a lot of others found lacking in TCL programs for beginners 1-10. This is meant as an introduction, not a complete description. By the way, I always wondered why the matching bracket thing is not documented in the 11 rules of Tcl: http://www.tcl.tk/man/tcl8.4/TclCmd/Tcl.htm

Also, with regards to wiki rules about editing other's post. If the changes in the comments are implemented, can I delete the comment? Also, I hope others won't mind if I later re-arrange parts of this page to make it more coherent overall.

Lars H: The "no unmatched braces in comments" restriction is only relevant in bodies (of proc, foreach, while, etc.), so it is natural to bring up in that context, but this is too early -- there hasn't yet been any example where a comment with an unmatched brace would spoil anything!


DO

  • Do write lots of comments in your code about what your code does, what you tried that didn't work (and why, if known).
  • Do study the documentation and others' code to understand 'upvar', 'uplevel'.

DON'T

  • Don't have unmatched brackets ANYWHERE, including comments. Use a text editor that helps you by showing bracket matching.
  • Don't expect to use an array in a proc till you understand 'upvar'. (CL strongly disagrees.)
  • Don't expect to drive external programs easily till you get the hang of 'exec'.

Especially Useful Tcl Features

  • foreach is wonderful. Simple and powerful.

Code reusing and packaging

  • tcllib is full of useful code. Try to use it as much as possible, a wide use of tcllib really saves time, and it is frequently updated.
  • If you need speed, be aware that Tcl can be extended easily (using C,C++...). Avoid writing your own extensions if existing ones can do the job.
  • Do split your code into different namespaces (and files) when it overcomes ca. a thousand lines.

Regarding Variables and Values example

set foo "this is cool"
set bar foo
puts [set $bar]
puts [set [set bar]]

yet another line to add to example code:

puts [expr $$bar]

wjk -- Totally agree with comment below by Lars H

Lars H: I don't think that would be a good idea, because [expr $$bar] combines two bad habits for a Tcl programmer: not bracing expressions and $ signs that fail to substitute. It can at best be a specimen for illuminating some of the odd quirks of the language, but it is definitely not something beginners should be exposed to.


See Also

   [Learning tcl]:  the first stop for those learning Tcl
Tcl Advocacy
Why Tcl is a great language to learn
  • "Five Surprises from Tcl" [L1 ] is probably best for programmers who don't work with the language but think they already knows its capabilities and limits
  • "Tcl The Misunderstood" [L2 ], a marvelously-written piece by antirez
  • All Tcl-related tutorials [L3 ]