TCLWISE
An introduction to the Tcl programming language

Sponsored Project: The Jim interpreter
A small footprint implementation of Tcl

Send a comment to the author


3. EVERYTHING IS A STRING


In Tcl every kind of data is represented by strings: numbers, lists, code, dictionaries. The user should not care to provide a command with the right data type: "2" is the same as 2, or { 2} for Tcl: it's the number two if a given procedure what to interpret it this way, or may be just a string for another procedure, so arguments of commands are always just strings that the commands will interpret in some way.

For instance, to compute mathematical expressions in Tcl there is a command called expr, that gets a mathematical expression as argument and returns the value of the expression.

% expr 20+30 50 %

but I may also write this code:

% set a "2"; set b "0+30"; expr $a$b 50 %

It looks strange no? Well, but actually it's logical. The Tcl interpreter will substitute $a and $b with "2" and "0+30", and then call expr with the argument "20+30". The expr command accepts more than one argument so that the mathematical expressions can be mixed with spaces:

% expr 1 + 2 * 40 81

Expr is also able to compute boolean experssions:

% set a 5; set b 2 2 % expr $a > $b 1

It returns 1 because 5 > 2. Like in C, expr's logical expressions will return 1 for true, and 0 for false.

You may wonder why math in Tcl is not accomplished using a command for every mathematical operand, like a command for +, one for -, and so on, like this:

% + 1 2 3

And this:

% + 1 [* 2 40] 81

Just for the user convenience. Personally I prefer this way, but the Tcl designers introduced expr because most people write math expressions in the infix notation at school. And actually for complex math expressions it's quite comfortable. Still there is a proposal to add this commands to Tcl. But of course we can define our own procedures in Tcl, so let's show how to create a + command if we like it.

3.1 User defined procedures


To create a procedure, the proc command is used:

% proc + {a b} {expr $a+$b} % + 3 4 7

Now we have a + procedure that can be used like any other Tcl procedure but it's better to analyze the arguments that the proc command needed to create the procedure. The first argument is the name of the procedure we want to create, "+". The second is a string representing the parameters that the procedure takes in input, that are a and b. The parameters are passed to proc as an unique string where every element is separated with a space. The final argument is a string representing the Tcl code to execute every time the + procedure is called.

So when I call the command +, the code "expr $a+$b" is executed in a context where the varialbes a and b have the value of the arguments passed to the procedure. The return value is the result of the expression, because for default a Tcl procedure returns the value returned by the last command executed.

There is a very important thing to note. The proc procedure creates other procedures, but it has nothing of special, it's just a Tcl procedure itself, that takes strings as arguments. Now the importance of grouping via { and } should be clear. If we write instead:

proc + "a b" "expr $a+$b"

We get an error:

% proc + "a b" "expr $a+$b" can't read "a": no such variable while evaluating {proc + "a b" "expr $a+$b"}

The Tcl interpreter try to expand $a and $b before to call the proc command. Note that it's possible to use the backslash to quote the $ character, so the same code may actually be written like:

% proc + "a b" "expr \$a+\$b" % + 1 1 2

As you can see proc is just a procedure, and { and } don't identify a block of code like in C, but just string grouping. All is a string. You may even redefine the proc command if you wish.

% proc proc {a b} {puts "$a likes $b"} % proc Bill Windows Bill likes Windows

Don't do it for now ;) You will find there are interesting uses even for this later. If you redefined the proc command with the last example, just restart the tclsh, otherwise you will not able to create new procedures.

3.2 The if command


Let's show a new command: if. It is like the if in any other language, but again it is a command that takes strings. The following is an example of code using if. This time don't type the code into the tclsh, but in a file using an editor, and execute it passing the file name to the tclsh.

proc abs x { if {$x > 0} { return $x } else { expr -$x } }

puts [abs 10] puts [abs -13]

The code above creates an abs proc that returns the absolute value of a number (that's, x if x > 0, 0-x if x < 0). In this example the if command takes four arguments. The first is an expression to test: if will test this expressions calling the expr procedure internally, if the result is true, the code passed as second argument is executed, otherwise the code passed as last argument is executed. In the abs procedure we use the first time the return command. It's goal is to abandon the execution of the current procedure, continuing the execution of the calling procedure, and returing the value specified ($x in the "return $x" command above).

There is an interesting detail to note. As you already know, different commands are separeted with new lines. So it's valid to write:

if {$a > 4} { puts Hello! }

Or instead just:

if {$a > 4} {puts Hello!}

But I can't write this:

if {$a > 4} { puts Hello! }

Because there are two commands. The first is if with an argument, and the second is the { ... puts Hello! ... } command! But still of course we like to indent the code nicely, in order to do so it's just enough to use the form:

if {$a > 4} { puts Hello! }

Because the second arguments start with a { character, it will take all the rest as a single argument until the next } is encountered. Grouping is not stopped by newlines. So actually with expr and grouping Tcl programs appear more or less like programs written in C from the point of view of syntax, while in some way they should be more similar to other languages using the infix form, like Lisp.

But we need to say a bit more on the if command, for example that in the simple form: if <expression> <truebranch> else <falsebranch> you can omit the "else".

% if 1 {puts Hello!} {puts Ciao!}

It will work the same as if there was "else" between the two last arguments. The second thing to note is that being if a command, it returns a value, and particuarly it returns the value returned by the last command called, so for example you can write:

% set max [if {$a > $b} {expr $a} {expr $b}]

C programmers may notice how this is similar to the ternary operator. In the above example expr is used just to make sure that the last command of both the branches returns the numeric value we are interested in.

The last thing to know (at least for now) about if, is that the syntax to write the if/elseif/elseif/else form is the following:

if {$a > 0} { set x "It's positive" } elseif {$a < 0} { set x "It's negative" } else { set x "It's zero" }

The if procedure is not the only conditional that's included by default in every Tcl interpreter. There is also switch, and other flow control commands like for and while. Also the user can create new conditionals or looping commands (but that's an argument for a successive chapter).

Other Tcl/Tk books
Index
2.1 Anatomy of a command
2.2 Grouping
2.3 Program structure
2.4 Substitution of commands
2.5 Substitution of variables
2.6 More on interpolation
2.7 Comments
2.8 That's it
3.1 User defined procedures
3.2 The if command
4.1 Tcl list
4.2 The foreach command
4.3 The lrange command
4.4 The lappend command
4.5 The lset command
4.6 The lsort command
4.7 List values against variable names
5.1 The append command
5.2 The string command
5.3 string range
5.4 string index
5.5 string equal
5.6 string compare
5.7 string match
5.8 string map
5.9 string is
5.10 More string subcommands
5.11 Advanced string matching
6.1 Converting strings to lists
6.2 From strings to list of chars
6.3 Converting lists to strings
6.4 Manipulating strings as lists
7.1 Local variables
7.2 Top level
7.3 Global variables
7.4 Procedures arguments and pass by value
7.5 Procedures with a variable number of arguments
7.6 Procedures with default arguments
7.7 Recursion
7.8 Recursion limit
8.1 The switch command
8.2 The for command
8.3 break and continue
8.4 The lack of goto
9.1 Programs executing programs: the eval command
9.2 Breaking the rules with uplevel
9.3 Passing variable names to procedures
9.4 Mapping scripts to lists
9.5 The rename command
9.6 Expanding lists into arguments in Tcl 8.5
Additional 20 chapters in the printed version.

Related man pages


Links
Author Home
Tclers Wiki


Copyright © 2004 Salvatore Sanfilippo. All rights reserved.
This online book is for personal use only.
It cannot be copied to other web sites or further distributed in any form.