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 :
If the word is surrounded by " ", this word may contain spaces, but
substitution is still applicable inside the quotations. Inside the
quotation, there may be spaces and carriage returns.
If a word is surrounded by { }, this word is unaffected (substitution
is thus not applicable on this word). Inside the braces, there may be
spaces and carriage returns. Moreover, the { } braces may be nested.
If a part of the word is surrounded by [ ], this part is considered as
a command sentence : the text within the brackets is evaluated as a Tcl
command and replaced with the result.
where substitution is applicable, every string beginning with $ is
replaced with the variable represented by this string. This string is
ended by a space, a '-' or a ','.
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 :
'if' is the first : nothing to be evaluated.
'$c == "Hell"' is the second : because of the surrounding curly braces,
there is no further evaluation on this word.
'puts "Oh god !"' : for the same reason, no further evaluation
'else' : nothing to do.
'puts "Peace !"' : no further evaluation.
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.

