computer tutorial 


TCL TUTORIAL


Tcl Tutorial

Introduction

This is a very short introduction to the Tcl script language. If you just can't wait, I hope this will make you able to read and to understand simple Tcl code.

In many points, Tcl is similar to C, especially for loop structures, function definitions and mathematical or conditional expressions. In other points, such as expression evaluation and list data structures, you will notice that Tcl has inherited from the benefits of the Scheme language.

In Tcl, all data is represented as strings.

Commands evaluation

Each Tcl command call is a sentence of the form : command arg1 arg2 arg3 ...

The Tcl evaluator take each word of this sentence and evaluate it. After evaluation of each word, the first word (command) is considered to be a function name and this function is executed with as arguments the following words.

To evaluate a word, the interpretor has to do the following substitutions in the word string :



Examples
set a "World !"
In the evaluation of the 3 words 'set', 'a' and '"World !"', no substitution has to be done, only the " " are removed. The command 'set' is then executed with as parameters 'a' and 'World !'. This command tell Tcl to define a new variable 'a' (if not already defined) and to set its value to 'World !'.

set b "Hello $a"
Set the variable 'b' to 'Hello World !'. Here, the variable substitution has occurred inside the second parameter where the variable 'a' is replaced by its value.

set c [string range $b 0 3]
Set the variable c to 'Hell', which is the 4 first letters of 'Hello World !'. In this case, The part between [ ] has been executed as a command

If you want to break a command sentence in lines you can only do it inside the { } brace or in the " " quotation or you can break the line with a '\' at the end of any break line.

Example

Code:

if {$c == "Hell"} {
   puts "Oh god !"
} else {
   puts "Peace !"
}



This test the value of the variable c. If it is the string 'Hell' it prints 'Oh god !' on screen, otherwise, it prints 'Peace !'. In this sentence, Tcl see 5 words :



The first word, 'if' is seen as the command and this command is executed with as parameters the 4 following words. That is later that the condition '$c == "Hell"' is evaluated, during the execution of the if command.

Notice where we placed the line breaks (inside the { }).

Strings and Lists

Under Tcl, the value of each variable is stored as a string. Even if you want to save a number in a variable, this number is transformed into a string.

As a special type of string, the list deserve a special attention in data representation in Tcl. The list is nothing more than a string with, as elements separator, the space. A list may contains sublists.

Example

Code:

% set list {12 {78 5} 45 "Im a not a number"}
12 {78 5} 45 "Im a not a number"
% set sublist1 [lindex $list 1]
78 5
% set sublist2 [lindex $list 3]
Im a not a number
% lindex $sublist2 2
not



Mathematics expression.

Whereas all variables are of type string, the mathematical operations internally uses float and integer number representation to produce their results. The command that calculate mathematical expression is 'expr'.

Example

Code:

% set result [expr (4+6)/4]
2
% set result [expr (4.0+6)/4]
2.5



In the first calculation, the interpretor has used the integer number representation. In the second, it has used the float number representation.

How to display something ?

To display a string, you can use the command 'puts'

Example

Code:

% set variable 255
% puts "The number $variable"
The number 255
% puts [format "The number %d is equal to 0x%02X" \
  $variable $variable]
The number 255 is equal to 0xFF



As it can be seen in the previous example, the command format is very similar to the C command 'printf'.

Control flow

The following commands are similar to the C equivalent. Only 'foreach' has no C equivalent (have a look at the example to see what it do).
if {...condition...} {...body...}
while {...condition...} {body}
for {... init ...} {...condition...} {...increment...} {...body...}
foreach varnames {...list...} {...body...}
the '...condition...' is evaluated in the same way that it should be with command 'expr'.

Examples

Code:

while

% while {$i<4} {
> puts "$i*$i is [expr $i*$i]"
> incr i
> }
0*0 is 0
1*1 is 1
2*2 is 4
3*3 is 9
for

% for {set i 0} {$i<4} {incr i} {
> puts "$i*$i is [expr $i*$i]"
> }
0*0 is 0
1*1 is 1
2*2 is 4
3*3 is 9
foreach

% set observations \
  {Bruxelles 15 22 London 12 19 Paris 18 27}
Bruxelles 15 22 London 12 19 Paris 18 27
% foreach {town Tmin Tmax} $observations {
> set Tavg [expr ($Tmin+$Tmax)/2.0]
> puts "$town $Tavg"
> }
Bruxelles 18.5
London 15.5
Paris 22.5



Array

Arrays are always unidimensional but the index is a string. If you use a separator in the index string (such as ',', '-'), you can get the same effect than with a multidimensional array in other languages.

Example

Code:

% set observations \
  {Bruxelles 15 22 London 12 19 Paris 18 27}
Bruxelles 15 22 London 12 19 Paris 18 27
% foreach {town Tmin Tmax} $observations {
set obs($town-min) $Tmin
set obs($town-max) $Tmax
}
% parray obs
obs(Bruxelles-max) = 22
obs(Bruxelles-min) = 15
obs(London-max)    = 19
obs(London-min)    = 12
obs(Paris-max)     = 27
obs(Paris-min)     = 18
Procedures



Procedures are the equivalent of the C functions.

Example

Code:

% proc sum2 {a b} {
>  return [expr $a+$b]
> }

if a procedure does not contain any 'return' statement, the default return value is the return value of the last evaluated function in this procedure. So the following script is perfectly equivalent :

Code:

% proc sum2 {a b} {
>   expr $a + $b
> }

  To call the 'sum2' function, we do the following :

Code:

% sum2 12 5
17

The special argument name 'args' contains a list with the rest of the arguments

Example

Code:

% proc sum {args} {
>   set result 0
>   foreach n $args {
>      set result [expr $result+$n]
>   }
>   return $result
> }
% sum 12 9 6 4
31



it is also possible to specify default parameters. So, if you don't specify the last parameters, the default values will be substituted.

Example.

Code:

% proc count {start end {step 1}} {
>   for {set i $start} {$i<=$end} {incr i $step} {
>     puts $i
>   }
> }
% count 1 3
1
2
3
% count 1 5 2
1
3
5

  If you want to use global variables in a function, you have to declare it as global.

Example

Code:

% set global_counter 3
% proc incr_counter {} {
>    global global_counter
>    incr global_counter
> }
% incr_counter
4
% set global_counter
4

You can also declare a table as global.

Example.

Code:

% set counter(value) 3
% set counter(active) 1
% proc incr_counter {} {
>    global counter
>    if {$counter(active)} {
>       incr counter(value)
>    }
> }
% incr_counter
4
% set counter(active) 0
0
% incr_counter
4

 Eval

The 'eval' command
concatenate all its arguments in one string
splits this string using spaces as separators
evaluate the command sentence formed by all the substrings

In the following example, we used the function 'sum' that we have already defined.

Example

Code:

%  proc average {args} {
>     return [expr [eval sum $args] / [llength $args]]
>  }
% average 45.0 65.0 78.0 55.0
60.75

If you had omitted the 'eval' command in the previous example, the 'sum' procedure would have returned an error because 'sum' should be called with only one string argument (in the previous example, this argument would have been '45.0 65.0 78.0 55.0') while 'sum' is expecting numerical arguments.
uplevel, upvar

With the 'upvar' command, you can access a variable which belongs to a higher level of the procedure call stack.

Example

Code:

% proc decr {n steps} {
>   upvar $n upa
>   set upa [expr $upa - $steps]
> }
% set nb 12
12
% decr nb 3
9
% puts $nb
9

  In the previous example, the parameter 'n' gets the value 'nb' (the string 'nb' !) if we type 'decr nb 3'. The command 'upvar $n upa' means that the variable 'upa' becomes a synonym to the variable 'nb' (coming from a higher level of the stack).

With the 'uplevel' command, you can evaluate something on higher level in the stack.

Example

Code:

% proc do {todo condition} {
>   set ok 1
>   while {$ok} {
>     uplevel $todo
>     if {[uplevel "expr $condition"]==0} {set ok 0}
>   }
> }
% set i 0
0
% do {
puts $i
incr i
} {$i<4}
0
1
2
3

Inside the procedure 'do', the evaluation of the script 'todo' and the conditional 'condition' has to made on a higher level of stack (in the same way that if they were evaluated from out of 'do').
error and catch

If you insert an 'error' command in your code, this command will stop the execution of your script and return the error message that follow the 'error' command. With the command 'catch', you can also intercept a error to avoid that your script stops on an error.

If 'catch' return 0, it means that no error occurred while evaluating the script send as parameter of catch. If 'catch' return 1, it means that an error occurred.

Example.

Code:

% proc div {a b} {
>   if {$b==0} {
>      error "divided by zero"
>   } else {
>      return [expr $a/$b]
>   }
> }
% div 8 3
2
% div 8 0
divide by zero
% catch {div 8 3}
0
% catch {div 8 0}
1
% catch {set result [div 8 3]}
0
% catch {set result [div 8 0]}
1

  The last call is completely equivalent to

Code:

catch {div 8 3} result

















Original Tutorial by Acidtone for TheTAZZone-TAZForum

Originally posted on June 20th, 2006 here

Do not use, republish, in whole or in part, without the consent of the Author. TheTAZZone policy is that Authors retain the rights to the work they submit and/or post...we do not sell, publish, transmit, or have the right to give permission for such...TheTAZZone merely retains the right to use, retain, and publish submitted work within it's Network.