Showing posts with label Tcl. Show all posts
Showing posts with label Tcl. Show all posts

Step By Step Tcl programming Tutorials For Beginners

Tcl tutorial

This is Tcl tutorial. In this tutorial you will learn Tcl language. The tutorial is suitable for beginners.

Table of contents

Tcl

Tcl is a string based scripting language. The source code is compiled into bytecode, which is later interpreted by the Tcl interpreter. It was created by John Osterhout in 1988. The language is commonly used for rapid prototyping, scripted applications, GUIs and testing. The Tcl stands for tool command language, where the source code of a Tcl script consists of commands.
Continue Reading

Input And output in Tcl programming

Input And output in Tcl

In this chapter, we will work with input, output operations in Tcl. Tcl has several commands for doing io. We will cover a few of them.
Tcl uses objects called channels to read and write data. The channels can be created using the open or socket command. There are three standard channels, which are available to Tcl scripts without explicitly creating them. They are automatically opened by the OS for each new application. They are stdin, stdout and stderr. The standard input, stdin, is used by the scripts to read data. The standard output, stdout, is used by scripts to write data. The standard error stderr is used by scripts to write error messages.
In the first example, we will work with the putscommand. It has the following synopsis:
puts ?-nonewline? ?channelId? string
The channelId is the channel, where we want to write text. The channelId is optional. If not specified, the default stdout is assumed.
$ cat print.tcl
#!/usr/bin/tclsh

puts "Message 1"
puts stdout "Message 2"
puts stderr "Message 3"
The puts command writes text to the channel.
puts "Message 1"
If we do not specify the channelId, we write to stdout by default.
puts stdout "Message 2"
This line does the same thing as the previous one. We only have explicitly specified the channelId.
puts stderr "Message 3"
We write to the standard error channel. The error messages go to the terminal by default.
$ ./print.tcl
Message 1
Message 2
Message 3
Output.

In the next example, we will be reading from the standard input channel.
#!/usr/bin/tclsh

puts -nonewline "Enter your name: "
flush stdout
set name [gets stdin]

puts "Hello $name"
The script asks for input from the user and then prints a message.
puts -nonewline "Enter your name: "
The puts command is used to print messages to the terminal. But the command can write to any channel, not just terminal.
flush stdout
Tcl buffers output internally, so characters written with puts may not appear immediately on the output file or device. We can force output to appear immediately with the flush command.
set name [gets stdin]
The gets command reads a line from a channel.
$ ./hello.tcl
Enter your name: Jan
Hello Jan
Sample output of the script.

The read command is used to read data from the channel.
#!/usr/bin/tclsh

set c [read stdin 1]

while {$c != "q"} {

puts -nonewline "$c"
set c [read stdin 1]
}
The script reads a character from the standard input channel and then writes it to the standard output until it encounters a q character.
set c [read stdin 1]
We read one character from the standard input channel (stdin).
while {$c != "q"} {
We continue reading characters until the q is pressed.

Tcl has pwd and cd commands, similar to shell commands. The pwd command returns the current working directory and the cd command is used to change the working directory.
#!/usr/bin/tclsh

set dir [pwd]

puts $dir

cd ..

set dir [pwd]
puts $dir
In this script, we will print the current working directory. We change the working directory and print the working directory again.
set dir [pwd]
The pwd command returns the current working directory.
cd ..
We change the working directory to the parent of the current directory. We use the cd command.
$ ./cwd.tcl 
/home/vronskij/programming/tcl/io
/home/vronskij/programming/tcl
Output.

Tcl has a glob command, which returns the names of the files that match a pattern.
#!/usr/bin/tclsh

set files [glob *.tcl]

foreach file $files {

puts $file
}
The script prints all files with .tcl extension to the console.
set files [glob *.tcl]
The glob command returns a list of files that match the *.tcl pattern.
foreach file $files {

puts $file
}
We go through the list of files and print each item of the list to the console.
$ ./glob.tcl
isfile.tcl
readfile.tcl
attributes.tcl
allfiles.tcl
cwd.tcl
addnumbers.tcl
glob.tcl
write2file.tcl
files.tcl
An example from a certain directory.

In the following code example, we are going to check if a file name is a regular file or a directory.
#!/usr/bin/tclsh

set files [glob *]

foreach fl $files {

if {[file isfile $fl]} {

puts "$fl is a file"
} elseif { [file isdirectory $fl]} {

puts "$fl is a directory"
}
}
We go through all file names in the current working directory and print whether it is a file or a directory.
set files [glob *]
Using the glob command we create a list of file and directory names of a current directory.
if {[file isfile $fl]} {
We execute the body of the if command, if the file name in question is a file.
} elseif { [file isdirectory $fl]} {
The file isdirectory command determines, whether a file name is a directory. Note that on Unix, a directory is a special case of a file.

Next, we are going to write to a file.
#!/usr/bin/tclsh

set fp [open days w]

set days {Monday Tuesday Wednesday Thursday Friday Saturday Sunday}

puts $fp $days
close $fp
In the script, we open a file for writing. We write days of a week to a file.
set fp [open days w]
We open a file named "days" for writing. The opencommand returns a channel id.
set days {Monday Tuesday Wednesday Thursday Friday Saturday Sunday}
This data is going to be written to the file.
puts $fp $days
We used the channel id returned by the open command to write to the file.
close $fp
We close the opened channel.
$ ./write2file.tcl
$ cat days
Monday Tuesday Wednesday Thursday Friday Saturday Sunday
We run the script and check the contents of the days file.

In the following script, we are going to read data from a file.
$ cat languages 
Python
Tcl
Visual Basic
Perl
Java
C
C#
Ruby
Scheme
We have a simple file called languages in a directory.
#!/usr/bin/tclsh

set fp [open languages r]
set data [read $fp]

puts -nonewline $data

close $fp

set fp [open languages r]
We create a channel by opening the languages file in a read-only mode.
set data [read $fp]
If we do not provide a second parameter to the readcommand, it reads all data from the file until the end of the file.
puts -nonewline $data
We print the data to the console.
$ ./readfile.tcl 
Python
Tcl
Visual Basic
Perl
Java
C
C#
Ruby
Scheme
Sample run of the readfile.tcl command.

The next script performs some additional file operations.
#!/usr/bin/tclsh

set fp [open newfile w]

puts $fp "this is new file"
flush $fp

file copy newfile newfile2
file delete newfile

close $fp
We open a file and write some text to it. The file is copied. The original file is then deleted.
file copy newfile newfile2
The file copy command copies a file.
file delete newfile
The original file is deleted with the file delete command.

In the final example, we will work with file attributes.
#!/usr/bin/tclsh

set files [glob *]

set mx 0

foreach fl $files {

set len [string length $fl]

if { $len > $mx} {

set mx $len
}
}

set fstr "%-$mx\s %-s"
puts [format $fstr Name Size]

set fstr "%-$mx\s %d bytes"
foreach fl $files {

set size [file size $fl]

puts [format $fstr $fl $size]

}
The script creates two columns. In the first column, we have the name of the file. In the second column, we display the size of the file.
foreach fl $files {

set len [string length $fl]

if { $len > $mx} {

set mx $len
}
}
In this loop, we find out the most lengthy file name. This will be used when formatting the output columns.
set fstr "%-$mx\s %-s"
puts [format $fstr Name Size]
Here we print the headers of the columns. To format the data, we use the format command.
set fstr "%-$mx\s %d bytes"
foreach fl $files {

set size [file size $fl]

puts [format $fstr $fl $size]

}
We go through the list of files and print each file name and its size. The file size command determines the size of the file.
$ ./attributes.tcl 
Name Size
isfile.tcl 219 bytes
readfile.tcl 98 bytes
tmp 4096 bytes
attributes.tcl 337 bytes
allfiles.tcl 75 bytes
read.tcl~ 114 bytes
cwd.tcl 76 bytes
Sample run.
In this chapter, we have covered Input/Output operations in Tcl.
Continue Reading

Procedures in Tcl programming

Procedures in Tcl

In this part of the tutorial, we will cover Tcl procedures.
A procedure is a code block containing a series of commands. Procedures are called functions in some programming languages. It is a good programming practice that procedures do only one specific task. Procedures bring modularity to programs. Proper use of procedures bring the following advantages:
  • Reducing duplication of code
  • Decomposing complex problems into simpler pieces
  • Improving clarity of the code
  • Reuse of code
  • Information hiding
There are two basic types of procedures. Built-in procedures and user defined ones. The built-in procedures are part of the Tcl core language. Examples are: rand(), sin() or exp(). The user defined functions are functions created with the proc keyword.
The term procedures and commands are often used interchangeably. In other words, the proc keyword is used to create new Tcl commands.
We start with a simple example.
#!/usr/bin/tclsh

proc tclver {} {

set v [info tclversion]
puts "this is tcl version $v"
}

tclver
In this script, we create a simple tclver procedure. The procedure prints the version of Tcl language.
proc tclver {} {
The new procedure is created with the proc command. The {} characters tell us, that the procedure takes no arguments.
    {

set v [info tclversion]
puts "this is tcl version $v"
}
This is the body of the tclver procedure. It is executed, when we execute the tclver command. The body of the command lies between the curly brackets.
tclver
The procedure is called by specifying its name.
$ ./version.tcl 
this is tcl version 8.5
Sample output.

Procedure arguments

An argument is a value passed to the procedure. Procedures can take one or more arguments. If procedures work with data, we must pass the data to the procedures.
In the following example, we have a procedure which takes one argument.
#!/usr/bin/tclsh

proc ftc {f} {

return [expr $f * 9 / 5 + 32]
}

puts [ftc 100]
puts [ftc 0]
puts [ftc 30]
We create a ftc procedure, which transforms fahrenheit temperature to celsius temperature.
proc ftc {f} {
The procedure takes one parameter. Its name f will be used in the body of the procedure.
return [expr $f * 9 / 5 + 32]
We compute the value of the celsius temperature. The returncommand returns the value to the caller. If the procedure doesn't execute an explicit return, then its return value is the value of the last command executed in the procedure's body.
puts [ftc 100]
The ftc procedure is executed. It takes 100 as a parameter. It is the temperature in fahrenheit. The returned value is used by the putscommand, which prints it to the console.
$ ./fahrenheit.tcl
212
32
86
Output.

Next we will have a procedure, which takes two arguments.
#!/usr/bin/tclsh

proc maximum {x y} {

if {$x > $y} {

return $x
} else {

return $y
}
}

set a 23
set b 32

set val [maximum $a $b]
puts "The max of $a, $b is $val"
We have a maximum procedure, which returns the maximum of two values.
proc maximum {x y} {
The method takes two arguments.
if {$x > $y} {

return $x
} else {

return $y
}
Here we compute which number is greater.
set a 23
set b 32
We define two variables, which are to be compared.
set val [maximum $a $b]
We calculate the maximum of the two variables.
$ ./maximum.tcl
The max of 23, 32 is 32
Output.

Variable number of arguments

A procedure can take and process variable number of arguments. For this we use the special args argument.
#!/usr/bin/tclsh

proc sum {args} {

set s 0

foreach arg $args {

incr s $arg
}

return $s
}

puts [sum 1 2 3 4]
puts [sum 1 2]
puts [sum 4]
We define a sum procedure which adds up all its arguments.
proc sum {args} {
The sum procedure has a special args argument. It has a list of all values passed to the procedure.
foreach arg $args {

incr s $arg
}
We go through the list and calculate the sum.
puts [sum 1 2 3 4]
puts [sum 1 2]
puts [sum 4]
We call the sum procedure three times. In the first case, it takes 4 arguments, in the second case 2, in the last case one. We call the same method.
$ ./variable.tcl
10
3
4
Output.

Implicit arguments

The arguments in Tcl procedures may have implicit values. An implicit value is used, if no explicit value is provided.
#!/usr/bin/tclsh

proc power {a {b 2}} {

if {$b == 2} {
return [expr $a * $a]
}

set value 1

for {set i 0} {$i<$b} {incr i} {

set value [expr $value * $a]
}

return $value
}

set v1 [power 5]
set v2 [power 5 4]

puts "5^2 is $v1"
puts "5^4 is $v2"
Here we create a power procedure. The procedure has one argument with an implicit value. We can call the procedure with one or two arguments.
proc power {a {b 2}} {
The second argument b, has an implicit value 2. If we provide only one argument, the power procedure then returns the value of a to the power 2.
set v1 [power 5]
set v2 [power 5 4]
We call the power procedure with one and two arguments. The first line computes the value of 5 to the power 2. The second line value of 5 to the power 4.
$ ./implicit.tcl
5^2 is 25
5^4 is 625
Output.

Recursion

Recursion, in mathematics and computer science, is a way of defining functions in which the function being defined is applied within its own definition. In other words, a recursive function calls itself to do its job. Recursion is a widely used approach to solve many programming tasks.
Recursion calls have a limit in Tcl. There cannot be more than 1000 recursion calls.
A typical example of recursion is calculation of the factorial. Factorial n!, is the product of all positive integers less than or equal to n.
#!/usr/bin/tclsh

proc factorial n {

if {$n==0} {

return 1
} else {

return [expr $n * [factorial [expr $n - 1]]]
}
}

# Stack limit between 800 and 1000 levels

puts [factorial 4]
puts [factorial 10]
puts [factorial 18]
In this code example, we calculate the factorial of three numbers.
return [expr $n * [factorial [expr $n - 1]]]
Inside the body of the factorial procedure, we call the factorial procedure with a modified argument. The procedure calls itself.
$ ./recursion.tcl
24
3628800
6402373705728000
These are the results. If we tried to compute the factorial of 100, we would receive "too many nested evaluations" error.

Scope

A variable declared inside a procedure has a procedure scope. The scope of a name is the region of program text within which it is possible to refer to the entity declared by the name without qualification of the name. A variable which is declared inside a procedure has a procedure scope. It is also called a local scope. The variable is valid only in this particular procedure.
#!/usr/bin/tclsh

proc test {} {

puts "inside procedure"
#puts "x is $x"
set x 4
puts "x is $x"
}

set x 1

puts "outside procedure"
puts "x is $x"

test

puts "outside procedure"
puts "x is $x"
In the preceding example, we have an x variable defined outside and inside of the test procedure.
set x 4
puts "x is $x"
Inside the test procedure, we define an x variable. The variable has local scope. It is valid only inside this procedure.
set x 1

puts "outside procedure"
puts "x is $x"
We define an x variable outside the procedure. It has a global scope. The variables do not conflict, because they have different scopes.
$ ./scope.tcl
outside procedure
x is 1
inside procedure
x is 4
outside procedure
x is 1
Output.

It is possible to change the global variable inside a procedure.
#!/usr/bin/tclsh

proc test {} {

upvar x y
puts "inside procedure"
puts "y is $y"
set y 4
puts "y is $y"
}

set x 1

puts "outside procedure"
puts "x is $x"

test

puts "outside procedure"
puts "x is $x"
We define a global x variable. We change the variable inside the test procedure.
upvar x y
We refer to the global x variable by the name y with the upvar command.
set y 4
We assign a value to the local y variable and also change the value of the global x variable.
$ ./scope2.tcl
outside procedure
x is 1
inside procedure
y is 1
y is 4
outside procedure
x is 4
From the output we can see, that the test procedure has changed the x variable.

With the global command, we can refer to global variables from procedures.
#!/usr/bin/tclsh

proc test {} {

global x
puts "inside test procedure x is $x"

proc nested {} {
global x
puts "inside nested x is $x"
}
}

set x 1

test
nested

puts "outside x is $x"
In the above example, we have a test procedure and a nested procedure defined within the test procedure. We refer to the global x variable from both procedures.
global x 
puts "inside test procedure x is $x"
With the global command, we refer to the global x variable, defined outside the test procedure.
proc nested {} {
global x
puts "inside nested x is $x"
}
It is possible to create nested procedures. These are procedures defined inside other procedures. We refer to the global x variable with the global command.
test
nested
We call the test procedure and its nested procedure.
$ ./scope3.tcl
inside test procedure x is 1
inside nested x is 1
outside x is 1
Output.
In this part of the Tcl tutorial, we covered Tcl procedures.
Continue Reading

Arrays in Tcl programming

Arrays in Tcl

In this part of the Tcl programming tutorial, we will cover arrays. We will initiate arrays and read data from them.
An array in Tcl is a data structure, which binds a key with a value. A key and a value can be any Tcl string.
#!/usr/bin/tclsh

set names(1) Jane
set names(2) Tom
set names(3) Elisabeth
set names(4) Robert
set names(5) Julia
set names(6) Victoria

puts [array exists names]
puts [array size names]

puts $names(1)
puts $names(2)
puts $names(6)
We create a names array. The numbers are keys and the names are values of the array.
set names(1) Jane
In this line we set a value Jane to the array key 1. We can later refer to the value by the key.
puts [array exists names]
The array exists command determines, whether the array is created. Returns 1 if true, 0 otherwise.
puts [array size names]
We get the size of the array with the array size command.
puts $names(1)
We access a value from the array by its key.
$ ./names.tcl
1
6
Jane
Tom
Victoria
Output.

Arrays can be initiated with the array setcommand.
#!/usr/bin/tclsh

array set days {
1 Monday
2 Tuesday
3 Wednesday
4 Thursday
5 Friday
6 Saturday
7 Sunday
}

foreach {n day} [array get days] {

puts "$n -> $day"
}
We create a day array. It has 7 keys and values.
foreach {n day} [array get days] {
The array get command returns a list of key, value elements, which can be iterated with the foreach command.
$ ./days.tcl
4 -> Thursday
5 -> Friday
1 -> Monday
6 -> Saturday
2 -> Tuesday
7 -> Sunday
3 -> Wednesday
Output.

We show another way to traverse an array in Tcl.
#!/usr/bin/tclsh

array set nums { a 1 b 2 c 3 d 4 e 5 }

puts [array names nums]

foreach n [array names nums] {

puts $nums($n)
}
The script uses the array names command to traverse the array.
array set nums { a 1 b 2 c 3 d 4 e 5 }
We define a simple array.
puts [array names nums]
The array names returns a list containing the names of all of the elements in the array.
foreach n [array names nums] {

puts $nums($n)
}
We use the keys to get the values.
$ ./getnames.tcl 
d e a b c
4
5
1
2
3
Output.

In the last example of this chapter, we will show how to remove elements from the array.
#!/usr/bin/tclsh

set names(1) Jane
set names(2) Tom
set names(3) Elisabeth
set names(4) Robert
set names(5) Julia
set names(6) Victoria

puts [array size names]
unset names(1)
unset names(2)

puts [array size names]
We create a names array. We use the unset command to remove items from the array. We check the size of the array before and after we remove the two items.
set names(1) Jane
The set command is used to create an item in the array.
unset names(1)
We use the unset command to remove an element with key 1 from the array.
In this part of the Tcl tutorial, we worked with arrays.
Continue Reading

Lists in Tcl programming

Tcl lists

In this part of the Tcl tutorial, we will talk about lists.
Computer programs work with data. Spreadsheets, text editors, calculators or chat clients. Working with groups of data is a basic programming operation. In Tcl, the listis a basic data structure. It is an ordered collection of items. Items in lists are separated by white space.
Every item of the list is identified by its index. Lists do not have a fixed length. List elements can be strings, numbers, variables, files or other lists. We can nest lists into other lists to any depth.

Creating lists

There are several ways, how we can create lists in Tcl.
#!/usr/bin/tclsh

set l1 { 1 2 3 }
set l2 [list one two three]
set l3 [split "1.2.3.4" .]

puts $l1
puts $l2
puts $l3
We create tree lists and print their contents to the console.
set l1 { 1 2 3 }
The basic way to create a list is to put elements of the list inside the brackets. List elements are separated by space.
set l2 [list one two three]
Another way to create a list is to use the listcommand.
set l3 [split "1.2.3.4" .]
Some Tcl commands return a list as a result. In the above code line, the split command returns a list of numbers generated from a string.
$ ./createlists.tcl
1 2 3
one two three
1 2 3 4
Output of the createlists.tcl script.

Basic list operations

In this section, we introduce some basic operations on lists. We will mention tree commands, that operate on Tcl lists.
#!/usr/bin/tclsh

set nums { 1 2 3 4 5 6 7 }

puts [llength $nums]
puts [lindex $nums 2]
puts [lindex $nums 4]
puts [lrange $nums 1 3]
The script defines a list of numbers. We perform some operations on the list with specific list commands.
puts [llength $nums]
The llength command returns a length of the list.
puts [lindex $nums 2]
The lindex command returns an item on the third position of the list. The positions in Tcl lists start from 0.
puts [lrange $nums 1 3]
The lrange command returns a subset of the list.
$ ./basicoperations.tcl
7
3
5
2 3 4
Output.

Traversing lists

Now that we have defined lists and basic list operations, we want to go traverse the list elements. We show several ways how to go through the list items.
#!/usr/bin/tclsh

foreach item {1 2 3 4 5 6 7 8 9} {

puts $item
}
We go through list elements with the foreachcommand.
foreach item {1 2 3 4 5 6 7 8 9} {

puts $item
}
Each loop cycle the item variable has a value from the list of numbers.
$ ./traverse1.tcl
1
2
3
4
5
6
7
8
9
Ouput.

In the second example we will go through items of the days list using the while loop.
#!/usr/bin/tclsh

set days [list Monday Tuesday Wednesday Thursday \
Friday Saturday Sunday]
set n [llength $days]

set i 0

while {$i < $n} {

puts [lindex $days $i]
incr i
}
We traverse the list using a while loop. When working with a while loop, we also need a counter and a number of items in the list.
set days [list Monday Tuesday Wednesday Thursday \
Friday Saturday Sunday]
We create a list of days.
set n [llength $days]
The length of the list is determined with the llengthcommand.
set i 0
The is a counter.
while {$i < $n} {

puts [lindex $days $i]
incr i
}
The while loop executes the commands in the body, until the counter is equal to the number of elements in the list.
puts [lindex $days $i]
The lindex returns a value from the list pointed to by the counter.
incr i
The counter is increased.
$ ./traverse2.tcl
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
Sunday
Output.

List operations

Now we will have some other list commands.
#!/usr/bin/tclsh

set nums {4 5 6}
puts $nums

lappend nums 7 8 9
puts $nums

puts [linsert $nums 0 1 2 3]
puts $nums
We have a list of three numbers.
lappend nums 7 8 9
The lappend appends data to the list.
puts [linsert $nums 0 1 2 3]
The linsert inserts elements at a given index. The first number is the index. The remaining values are numbers to be inserted into the list. The command creates a new lists and returns it. It does not modify the original list.
$ ./operations.tcl 
4 5 6
4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
4 5 6 7 8 9
This is the output of the operations.tcl script.

In the following example, we will concatenate lists, search for items and replace items in lists.
#!/usr/bin/tclsh

set animals1 { lion eagle elephant dog cat }
set animals2 { giraffe tiger horse dolphin }

set animals [concat $animals1 $animals2]

puts $animals

puts [lsearch -exact $animals eagle]
puts [lreplace $animals 3 4 buffalo crocodile]
We define two animal lists. We introduce three new commands.
set animals [concat $animals1 $animals2]
The concat command is used to concatenate (add) two lists. The above line joins two lists and the new list is set to the animals variable.
puts [lsearch -exact $animals eagle]
With the lsearch command we look for an eagle in the list. With the -exact option we look for an exact match. The command returns the index of the first matching element. Or -1 if there is no match.
puts [lreplace $animals 3 4 buffalo crocodile]
The lreplace command replaces dog and cat with buffalo and crocodile.
$ ./operations2.tcl
lion eagle elephant dog cat giraffe tiger horse dolphin
1
lion eagle elephant buffalo crocodile giraffe tiger horse dolphin
Example output.

Sorting items

In this section, we will show how we can sort items in Tcl lists.
#!/usr/bin/tclsh

set names { John Mary Lenka Veronika Julia Robert }
set nums { 1 5 4 3 6 7 9 2 11 0 8 2 3 }

puts [lsort $names]
puts [lsort -ascii $names]
puts [lsort -ascii -decreasing $names]
puts [lsort -integer -increasing $nums]
puts [lsort -integer -decreasing $nums]
puts [lsort -integer -unique $nums]
To sort list elements, we can use the sort command. The command does not modify the original list. It returns a new sorted list of elements.
set names { John Mary Lenka Veronika Julia Robert }
set nums { 1 5 4 3 6 7 9 2 11 0 8 2 3 }
We have two lists. In the first we have strings, in the second numbers.
puts [lsort $names]
puts [lsort -ascii $names]
The default sorting is the ascii sorting. The elements are sorted by their positions in the ascii table.
puts [lsort -integer -increasing $nums]
puts [lsort -integer -decreasing $nums]
We treat the values as integers and sort them in increasing and decreasing orders.
puts [lsort -integer -unique $nums]
We sort the elements of the list in a numerical context in increasing order. Duplicates will be removed.
$ ./sorting.tcl
John Julia Lenka Mary Robert Veronika
John Julia Lenka Mary Robert Veronika
Veronika Robert Mary Lenka Julia John
0 1 2 2 3 3 4 5 6 7 8 9 11
11 9 8 7 6 5 4 3 3 2 2 1 0
0 1 2 3 4 5 6 7 8 9 11
Output.

Nested lists

In Tcl there can be nested lists; list in other lists.
#!/usr/bin/tclsh

set nums {1 2 {1 2 3 4} {{1 2} {3 4}} 3 4}

puts [llength $nums]
puts [llength [lindex $nums 2]]

puts [lindex $nums 0]
puts [lindex [lindex $nums 2] 1]
puts [lindex [lindex [lindex $nums 3] 1] 1]
This is a simple example with nested lists in Tcl.
set nums {1 2 {1 2 3 4} {{1 2} {3 4}} 3 4}
A list with two nested lists. The second list has two additional inner nested lists.
puts [llength $nums]
We determine the size of the list. The nested list is counted as one element.
puts [llength [lindex $nums 2]]
In this line, we determine the size of the first nested list, which is the third element of the main list.
puts [lindex $nums 0]
Here we print the first element of the main list.
puts [lindex [lindex $nums 2] 1]
In the above line, we get the second element of the first nested list.
puts [lindex [lindex [lindex $nums 3] 1] 1]
Here we get the second element of the second inner list of the inner list located at the 4th position of the main list. In other words: the inner most command is executed first. The [lindex $nums 3] returns {{1 2} {3 4}}. Now the second command operates on this returned list. [lindex {{1 2} {3 4}} 1] returns {3 4}. Finally, the last command [lindex {3 4} 1] returns 4, which is printed to the terminal.
$ ./nestedlists.tcl
6
4
1
2
4
Output.
In this part of the Tcl tutorial, we covered Tcl lists.
Continue Reading

Strings in Tcl programming

Strings in Tcl

In this part of the Tcl tutorial, we will work with string data in more detail. String is an important data type in computer languages.
A string is a sequence of characters. String in Tcl, unlike in other languages, may not be enclosed within double quotes. They are necessary only if we have a space between words. Tcl is a string based language. It provides a rich set of commands for manipulating strings.

First example

A simple example showing some strings follows.
#!/usr/bin/tclsh

puts Tcl
puts Java
puts Falcon

puts "Tcl language"
puts {Tcl language}
The script prints some string values to the console.
puts Tcl
puts Java
puts Falcon
Strings in Tcl may not be enclosed within quotes.
puts "Tcl language"
puts {Tcl language}
Strings in Tcl can be grouped with double quotes or curly brackets.
$ ./simple.tcl 
Tcl
Java
Falcon
Tcl language
Tcl language
Output.

Using quotes

What if we wanted to display quotes, for example in a direct speech? In such a case, inner quotes must be escaped.
$ cat directspeech.tcl
#!/usr/bin/tclsh

puts "There are many stars"
puts "He said, \"Which one is your favourite?\""
We use the (\) character to escape additional quotes.
$ ./directspeech.tcl
There are many stars
He said, "Which one is your favourite?"
Output.

Multiline strings

It is very easy to create a multiline string in Tcl. I many other languages creating multiline strings is much less convenient.
#!/usr/bin/tclsh

set lyrics "I cheated myself
like I knew I would
I told ya, I was trouble
you know that I'm no good"

puts $lyrics
We simple continue on the next line. This is useful if we wanted to display verses.
$ ./multiline.tcl
I cheated myself
like I knew I would
I told ya, I was trouble
you know that I'm no good

Comparing strings

Basic comparison of strings can be done with the string compare command.
#!/usr/bin/tclsh

puts [string compare 12 12]
puts [string compare Eagle Eagle]
puts [string compare Eagle eagle]
puts [string compare -nocase Eagle eagle]
The string compare command compares strings character by character. If it finds that the first characters of both strings are equal, it continues with the second character. Until the end. It returns 0, if the strings are equal. -1 if a character in the first string is located in the ascii table before the character of the second string. 1 if the character of the first string is located after the character of the second string.
puts [string compare 12 12]
In this context, 12 is a string.
puts [string compare Eagle Eagle]
Two strings are equal, 0 is printed to the console.
puts [string compare Eagle eagle]
E stands before e, -1 is returned.
puts [string compare -nocase Eagle eagle]
With the -nocase option, we ignore the case. The two strings are equal.
$ ./compare.tcl
0
0
-1
0
Output of the program.

The string equal also can be used to compare strings. The command returns 1, if the strings are equal, and 0 if they are not.
#!/usr/bin/tclsh

set str1 Tcl
set str2 "Tcl language"

puts [string compare $str1 $str2]
puts [string compare -length 3 $str1 $str2]

puts [string equal $str1 $str2]
puts [string equal -length 3 $str1 $str2]
The script shows both commands comparing strings.
puts [string compare $str1 $str2]
The line prints -1. The characters on the first three positions are equal. On the fourth position the string compare command compares white space with the l character. The space is located before the l character in the ascii table. Strings are not equal.
puts [string compare -length 3 $str1 $str2]
In this case, we limit the comparing to first three characters. They are same in both strings, so the command returns 0.
puts [string equal $str1 $str2]
The two strings are not identical, so the string equalcommand returns 0, for false.
puts [string equal -length 3 $str1 $str2]
Limiting strings to the first three characters, the command returns 1. Which means, they are identical up to the first three characters.

Unicode

We can use unicode strings in our Tcl scripts.
#!/usr/bin/tclsh

puts "La femme vit par le sentiment, là où l'homme vit par l'action"
puts "Анна Каренина"
We print two messages to the terminal. The first is in French, the second in Russian.
$ ./unicode.tcl
La femme vit par le sentiment, là où l'homme vit par l'action
Анна Каренина
Output.

String commands

Tcl has useful built-in commands that can be used for working with strings.
#!/usr/bin/tclsh

set str Eagle

puts [string length $str]

puts [string index $str 0]
puts [string index $str end]

puts [string range $str 1 3]
We define a string variable and work with some string commands.
puts [string length $str]
The string length returns the number of characters in the string.
puts [string index $str 0]
puts [string index $str end]
The string index command returns the character at a specific position.
puts [string range $str 1 3]
The string range returns a range of characters, selected by the first and last index.
$ ./strings1.tcl
5
E
e
agl
Output.

We have a split command to split strings at a specific character. The command returns a list of words. These words can be combined together into a string with the join command.
#!/usr/bin/tclsh

set langs "Tcl,Java,C,C#,Ruby,Falcon"

puts [split $langs ,]
puts [join [split $langs ","] ":"]
In our program, we will split and join strings.
set langs "Tcl,Java,C,C#,Ruby,Falcon"
This is a string we are going to split. There are several words separated by a comma character. The comma character is the character, by which we will split the string.
puts [split $langs ,]
The line prints all words that we have split from the string.
puts [join [split $langs ","] ":"]
The split command returns a list of words from the string. These words are then joined. The words will be now separated by the colon.
$ ./splitjoin.tcl 
Tcl Java C C# Ruby Falcon
Tcl:Java:C:C#:Ruby:Falcon
Output of the example.

Next we will have another example with a few string commands.
#!/usr/bin/tclsh

set str "ZetCode"

puts [string toupper $str]
puts [string tolower $str]
puts [string totitle $str]
puts [string reverse $str]
We introduce four string commands. The commands do not change the original string. They return a new, modified string.
puts [string toupper $str]
We convert the characters to uppercase.
puts [string tolower $str]
We convert letters of the string to lowercase.
puts [string totitle $str]
The string totitle returns a string with the first character in uppercase; other characters are in lowercase.
puts [string reverse $str]
We reverse the characters of the string with the string reverse command.
$ ./strings2.tcl 
ZETCODE
zetcode
Zetcode
edoCteZ
Running the program.

Formatting strings

The very basic formatting of strings is done within the quotes.
#!/usr/bin/tclsh

set oranges 2
set apples 4
set bananas 3

puts "There are $oranges oranges, $apples apples and\
$bananas bananas. "
Tcl evaluates variables in double quotes.
puts "There are $oranges oranges, $apples apples and\
$bananas bananas. "
In this code line, we combine variables and strings in one sentence.
$ ./fruit.tcl
There are 2 oranges, 4 apples and 3 bananas.
Output.

More advanced formatting can be done with the format command. It has the following synopsis.
format formatString ?arg arg ...?
The formatString is used to control, how the arguments are going to be displayed. The command can take multiple arguments.
#!/usr/bin/tclsh

puts [format %s "Inception movie"]
puts [format "%d %s" 23 songs]
This is basic script showing the usage of the format command.
puts [format %s "Inception movie"]
This line simply prints a string to the console.
puts [format "%d %s" 23 songs]
Here we print two arguments. Each argument has a format specifier, which begins with the % character.
$ ./basicformat.tcl
Inception movie
23 songs
Output.

Now we show some basic conversion specifiers for the format command. %s, %f, %d, %e are conversion types. They control how the value is displayed. Conversion type is the only mandatory part of the conversion specifier.
#!/usr/bin/tclsh

puts [format "%s" "Tcl language"]
puts [format "%f" 212.432]
puts [format "%d" 20000]
puts [format "%e" 212.342]
We will print four messages to the terminal.
puts [format "%s" "Tcl language"]
The %s is a conversion type for the string.
puts [format "%f" 212.432]
%f is used to display decimal numbers.
puts [format "%d" 20000]
To print an integer value, we use the %d conversion type.
puts [format "%e" 212.342]
The %e is used to show number in a scientific format.
$ ./format.tcl
Tcl language
212.432000
20000
2.123420e+02
Output.

In the next example, we will be formatting numbers in three different number formats.
#!/usr/bin/tclsh

puts [format "%-10s %-14s %s" Decimal Hexadecimal Octal]

puts [format "%-10d %-14x %o" 5000 5000 5000]
puts [format "%-10d %-14x %o" 344 344 344]
puts [format "%-10d %-14x %o" 55 55 55]
puts [format "%-10d %-14x %o" 9 9 9]
puts [format "%-10d %-14x %o" 15666 15666 15666]
We print numbers in a decimal, hexadecimal and octal format. We also align the numbers in three columns.
puts [format "%-10d %-14x %o" 5000 5000 5000]
The %-10d applies for the first number, %-14x for the second and %o for the third. We will describe the first one. The format specifier begins with the % character. The minus sign (-) tells, that if the value will be shorter than the field width, it is left justified. The rest of the field is padded with white space. The number (10) specifies the field width. Finally the d character tells that the number is displayed in decimal format. The x stands for hexadecimal and o for octal.
$ ./numbers.tcl
Decimal Hexadecimal Octal
5000 1388 11610
344 158 530
55 37 67
9 9 11
15666 3d32 36462
Running the example.

Finally, we will format date and time data. We use the clock format command.
#!/usr/bin/tclsh

set secs [clock seconds]

puts "Short date: [clock format $secs -format %D]"
puts "Long date: [clock format $secs -format "%A, %B %d, %Y"]"
puts "Short time: [clock format $secs -format %R]"
puts "Long time: [clock format $secs -format %r]"
puts "Month: [clock format $secs -format %B]"
puts "Year: [clock format $secs -format %Y]"
The preceding example demonstrates some common date and time formats.
set secs [clock seconds]
We get the current timestamp in seconds. This value is later passed to the clock format command, to get dates and times readable for humans.
puts "Short date: [clock format $secs -format %D]"
The format of the date is controlled with the -format option. There are several specifiers. The %D returns a date in month/day/year format.
$ ./clockformat.tcl
Short date: 04/11/2011
Long date: Monday, April 11, 2011
Short time: 11:30
Long time: 11:30:30 am
Month: April
Year: 2011
Output.
This part of the Tcl tutorial covered strings.
Continue Reading

Flow control in Tcl programming

Flow control in Tcl

In this part of the Tcl tutorial, we will talk about the flow control. We will define several commands that enable us to control the flow of a Tcl script.
In Tcl language there are several commands that are used to alter the flow of the program. When the program is run, the commands are executed from the top of the source file to the bottom. One by one. This flow can be altered by specific commands. Commands can be executed multiple times. Some commands are conditional. They are executed only if a specific condition is met.

The if command

The if command has the following general form:
if expr1 ?then? body1 elseif expr2 ?then? body2 elseif ... ?else? ?bodyN?
The if command is used to check if an expression is true. If it is true, a body of command(s) is then executed. The body is enclosed by curly brackets.
The if command evaluates an expression. The expression must return a boolean value. In Tcl, 1, yes, true mean true and 0, no, false mean false.
!/usr/bin/tclsh

if yes {
puts "This message is always shown"
}
In the above example, the body enclosed by { } characters is always executed.
#!/usr/bin/tclsh

if true then {
puts "This message is always shown"
}
The then command is optional. We can use it if we think, it will make the code more clear.

We can use the else command to create a simple branch. If the expression inside the square brackets following the if command evaluates to false, the command following the else command is automatically executed.
#!/usr/bin/tclsh

set sex female

if {$sex == "male"} {

puts "It is a boy"
} else {

puts "It is a girl"
}
We have a sex variable. It has "female" string. The boolean expression evaluates to false and we get "It is a girl" in the console.
$ ./girlboy.tcl 
It is a girl
We can create multiple branches using the elseif command. The elseif command tests for another condition, if and only if the previous condition was not met. Note, that we can use multiple elseif commands in our tests.
#!/usr/bin/tclsh

# nums.tcl

puts -nonewline "Enter a number: "
flush stdout
set a [gets stdin]

if {$a < 0} {

puts "the number is negative"
} elseif { $a == 0 } {

puts "the numer is zero"
} else {

puts "the number is positive"
}
In the above script we have a prompt to enter a value. We test the value. If it is a negative number or positive or if it equals to zero. If the first expression evaluates to false, the second expression is evaluated. If the previous conditions were not met, than the body following the else command would be executed.
$ ./nums.tcl 
Enter a number: 2
the number is positive
$ ./nums.tcl
Enter a number: 0
the numer is zero
$ ./nums.tcl
Enter a number: -3
the number is negative
Running the example multiple times.

The switch command

The switch command matches its string argument against each of the pattern arguments in order. As soon as it finds a pattern that matches string it evaluates the following body argument by passing it recursively to the Tcl interpreter and returns the result of that evaluation. If the last pattern argument is default then it matches anything. If no pattern argument matches string and no default is given, then the switch command returns an empty string.
#!/usr/bin/tclsh                                                                                              

puts -nonewline "Select a top level domain name "
flush stdout

gets stdin domain

switch $domain {

us { puts "United States" }
de { puts Germany }
sk { puts Slovakia }
hu { puts Hungary }
default { puts unknown }
}
In our script, we prompt for a domain name. There are several options. If the value equals for example to us the "United States" string is printed to the console. If the value does not match to any given value, the default body is executed and unknown is printed to the console.
$ ./switch.tcl 
Select a top level domain name sk
Slovakia
We have entered sk string to the console and the program responded with Slovakia.

The while command

The while command is a control flow command that allows code to be executed repeatedly based on a given boolean condition.
The while command executes the commands inside the block enclosed by the curly brackets. The commands are executed each time the expression is evaluated to true.
#!/usr/bin/tclsh

# whileloop.tcl

set i 0
set sum 0

while { $i < 10 } {

incr i
incr sum $i
}

puts $sum
In the code example, we calculate the sum of values from a range of numbers.
The while loop has three parts. Initialization, testing and updating. Each execution of the command is called a cycle.
set i 0
We initiate the i variable. It is used as a counter.
while { $i < 10 } {

...
}
The expression inside the square brackets following the whilecommand is the second phase, the testing. The commands in the body are executed, until the expression is evaluated to false.
incr i
The last, third phase of the while loop. The updating. We increment the counter. Note that improper handling of the while loops may lead to endless cycles.

The for command

When the number of cycles is know before the loop is initiated, we can use the for command. In this construct we declare a counter variable, which is automatically increased or decreased in value during each repetition of the loop.
#!/usr/bin/tclsh

for {set i 0} {$i < 10} {incr i} {
puts $i
}
In this example, we print numbers 0..9 to the console.
for {set i 0} {$i < 10} {incr i} {
puts $i
}
There are three phases. First, we initiate the counter i to zero. This phase is done only once. Next comes the condition. If the condition is met, the command inside the for block is executed. Then comes the third phase; the counter is increased. Now we repeat the 2, 3 phases until the condition is not met and the for loop is left. In our case, when the counter i is equal to 10, the for loop stops executing.

The foreach command

The foreach command simplifies traversing over collections of data. It has no explicit counter. The foreach command goes throught the list one by one and the current value is copied to a variable defined in the construct.
#!/usr/bin/tclsh

set planets { Mercury Venus Earth Mars Jupiter Saturn
Uranus Neptune }

foreach planet $planets {
puts $planet
}
In this example, we use the foreach command to go through a list of planets.
foreach planet $planets {
puts $planet
}
The usage of the foreach command is straightforward. The planets is the list, that we iterate through. The planet is the temporary variable, that has the current value from the list. The foreach command goes through all the planets and prints them to the console.
$ ./planets.tcl 
Mercury
Venus
Earth
Mars
Jupiter
Saturn
Uranus
Neptune
Running the above Tcl script gives this output.

#!/usr/bin/tclsh

set actresses { Rachel Weiss Scarlett Johansson Jessica Alba \
Marion Cotillard Jennifer Connelly}

foreach {first second} $actresses {
puts "$first $second"
}
In this script, we iterate througn pairs of values of a list.
foreach {first second} $actresses {
puts "$first $second"
}
We pick two values from the list at each iteration.
$ ./actresses.tcl 
Rachel Weiss
Scarlett Johansson
Jessica Alba
Marion Cotillard
Jennifer Connelly
Output of actresses.tcl.

#!/usr/bin/tclsh

foreach i { one two three } item {car coins rocks} {
puts "$i $item"
}
We can iterate over two lists in parallel.
$ ./parallel.tcl 
one car
two coins
three rocks
Output.

The break, continue commands

The break command can be used to terminate a block defined by while, foror switch commands.
#!/usr/bin/tclsh

while true {

set r [expr 1 + round(rand()*30)]
puts -nonewline "$r "

if {$r == 22} { break }
}

puts ""
We define an endless while loop. We use the break command to get out of this loop. We choose a random value from 1 to 30. We print the value. If the value equals to 22, we finish the endless while loop.
set r [expr 1 + round(rand()*30)]
Here we calculate a random number between 1..30. The rand() is a built-in Tcl procedure. It returns a random number from 0 to 0.99999. The rand()*30 returns a random number between 0 to 29.99999. The round() procedure rounds the final number.
$ ./breakcommand.tcl 
28 20 8 8 12 22
We might get something like this.

The continue command is used to skip a part of the loop and continue with the next iteration of the loop. It can be used in combination with for and while commands.
In the following example, we will print a list of numbers, that cannot be divided by 2 without a remainder.
#!/usr/bin/tclsh

set num 0

while { $num < 100 } {

incr num

if {$num % 2 == 0} { continue }

puts "$num "
}

puts ""
We iterate through numbers 1..99 with the while loop.
if {$num % 2 == 0} { continue }
If the expression num % 2 returns 0, the number in question can be divided by 2. The continue command is executed and the rest of the cycle is skipped. In our case, the last command of the loop is skipped and the number is not printed to the console. The next iteration is started.
In this part of the Tcl tutorial, we were talking about control flow structures.
Continue Reading

Expressions in Tcl programming

Expressions in Tcl

In this part of the Tcl tutorial, we will talk about expressions. In Tcl language the expressions are not built into the core language. Expressions are evaluated with the expr command.
Expressions are constructed from operands and operators. The operators of an expression indicate which operations to apply to the operands. The order of evaluation of operators in an expression is determined by the precedence and associativity of the operators.
An operator is a special symbol which indicates a certain process is carried out. Operators in programming languages are taken from mathematics. Programmers work with data. The operators are used to process data. An operand is one of the inputs (arguments) of an operator.
The following table shows a set of operators used in the Tcl language.
Category Symbol
Sign, bit-wise, logical NOT - + ~ !
Exponentiation **
Arithmetic + - * / %
Shift << >>
Relational == != < > <= >=
String comparison eq ne
List in ni
Bitwise & | ^
Boolean && ||
Ternary ?:

An operator usually has one or two operands. Those operators that work with only one operand are called unary operators. Those which work with two operands are called binary operators. There is also one ternary operator (?:), which works with three operands.

Basic operators

Basic operators are commonly used operators. These are sign operators, arithmetic operators, modulo and exponentiation operators.
#!/usr/bin/tclsh

puts [expr +2]
puts [expr -2]
puts [expr -(-2)]
puts [expr 2+2]
puts [expr 2-2]
puts [expr 2*2]
puts [expr 2/2]
puts [expr 2/2.0]
puts [expr 2 % 2]
puts [expr 2 ** 2]
The above example shows usage of common operators in Tcl.
puts [expr +2]
In this code line we use the plus sign operator. It has no effect on the number. It merely indicates that the number is positive. It can be omitted and most of the time it is.
puts [expr -2]
puts [expr -(-2)]
The minus operator is compulsory. It says that the number is negative. The minus operator changes the sign of the number. In the second line, the minus operator changes the -2 to positive 2.
puts [expr 2+2]
puts [expr 2-2]
puts [expr 2*2]
puts [expr 2/2]
The above lines show common arithmetic operators in use.
puts [expr 2 % 2]
The % is the modulo or remainder operator. It finds the remainder of division of one number by another. 2 % 2, 2 modulo 2 is 0 because 2 goes into 2 once with the remainder of 0. So the code line prints zero to the console.
puts [expr 2 ** 2]
This is the exponentiation operator. The code line prints 4 to the console.
$ ./exp.tcl
2
-2
2
4
0
4
1
1.0
0
4
Output of the example.

Division operator

Beginning programmers are often confused by division operation. In many programming languages there are two kinds of division operations. Integer and non-integer. This applies for the Tcl as well.
% expr 3/2
1
% expr 3/2.0
1.5
Note the difference between the integer and floating point division. When at least one of the operands is a floating point number, the result is a floating point value too. The result is more exact. If both operands are integers, the result is an integer too.

Assignment operator, increment operator

There is no assignment operator (=) and no increment/decrement (++/--) operators in Tcl. These operators are common in other computer languages. Instead of that, Tcl has commands.
% set a 5
5
% incr a
6
% incr a
7
% incr a -1
6
The above code shows what commands are used to implement the missing operators.
% set a 5
In Python, we would do a = 5. In Tcl, we set a value to a variable using the set command.
% incr a  
6
In C, Java and many other languages, we would increment a variable by one this way: a++;. In Tcl, we use the incrcommand. By default, the value is incremented by 1.
% incr a -1
6
The above code shows how to decrement a variable by one, which is accomplished commonly by the (--) decrement operator in other languages.

Boolean operators

In Tcl, we have the following logical operators. Boolean operators are also called logical.
SymbolName
&&logical and
||logical or
!negation
#!/usr/bin/tclsh

set x 3
set y 8

puts [expr $x == $y]
puts [expr $y > $x]

if {$y > $x} {

puts "y is greater than x"
}
Many expressions result in a boolean value. Boolean values are used in conditional statements.
puts [expr $x == $y]
puts [expr $y > $x]
Relational operators always result in a boolean value. These two lines print 0 and 1.
if {$y > $x} {

puts "y is greater than x"
}
The body of the if command is executed only if the condition inside the parentheses is met. The $y > $x returns true, so the message "y is greater than x" is printed to the terminal.

#!/usr/bin/tclsh

puts [expr 0 && 0]
puts [expr 0 && 1]
puts [expr 1 && 0]
puts [expr 1 && 1]
Example shows the logical and (&&) operator. It evaluates to true only if both operands are true.
$ ./andoperator.tcl 
0
0
0
1

The logical or (||) operator evaluates to true, if either of the operands is true.
#!/usr/bin/tclsh

puts [expr 0 || 0]
puts [expr 0 || 1]
puts [expr 1 || 0]
puts [expr 1 || 1]
If one of the sides of the operator is true, the outcome of the operation is true.
$ ./oroperator.tcl 
0
1
1
1

The negation operator (!) makes true false and false true.
#!/usr/bin/tclsh

puts [expr ! 0]
puts [expr ! 1]
puts [expr ! (4<3)]
The example shows the negation operator in action.
$ ./not.tcl 
1
0
1

The ||, and && operators are short circuit evaluated. Short circuit evaluation means that the second argument is only evaluated if the first argument does not suffice to determine the value of the expression: when the first argument of the logical and evaluates to false, the overall value must be false; and when the first argument of logical or evaluates to true, the overall value must be true. (wikipedia) Short circuit evaluation is used mainly to improve performance.
An example may clarify this a bit more.
#!/usr/bin/tclsh


proc One {} {

puts "Inside one"
return false
}

proc Two {} {

puts "Inside two"
return true
}

puts "Short circuit"

if { [One] && [Two] } {

puts "Pass"
}

puts "###################"

if { [Two] || [One] } {

puts "Pass"
}
We have two procedures in the example. (Procedures and conditionals will be described later.) They are used as operands in boolean expressions. We will see, if they are called or not.
if { [One] && [Two] } {

puts "Pass"
}
The One procedure returns false. The short circuit && does not evaluate the second procedure. It is not necessary. Once an operand is false, the result of the logical conclusion is always false. Only "Inside one" is only printed to the console.
puts "###################"

if { [Two] || [One] } {

puts "Pass"
}
In the second case, we use the || operator and use the Two procedure as the first operand. In this case, "Inside two" and "Pass" strings are printed to the terminal. It is again not necessary to evaluate the second operand, since once the first operand evaluates to true, the logical or is always true.
$ ./shortcircuit.tcl
Short circuit
Inside one
###################
Inside two
Pass
Result of the shorcircuit.tcl script.

Relational Operators

Relational operators are used to compare values. These operators always result in boolean value. In Tcl 0 stands for false and 1 for true. Relational operators are also called comparison operators.
SymbolMeaning
<less than
<=less than or equal to
>greater than
>=greater than or equal to
==equal to
!=not equal to
#!/usr/bin/tclsh

puts [expr 3 < 4]
puts [expr 3 == 4]
puts [expr 4 >= 3]
puts [expr 4 != 3]
In Tcl we use the == to compare numbers. Some languages like Ada, Visual Basic, or Pascal use = for comparing numbers.
$ ./rel.tcl
1
0
1
1
The example prints four boolean values.

Bitwise operators

Decimal numbers are natural to humans. Binary numbers are native to computers. Binary, octal, decimal or hexadecimal symbols are only notations of the same number. Bitwise operators work with bits of a binary number. Bitwise operators are seldom used in higher level languages like Tcl.
SymbolMeaning
~bitwise negation
^bitwise exclusive or
&bitwise and
|bitwise or
The bitwise negation operator changes each 1 to 0 and 0 to 1.
% puts [expr ~7] 
-8
% puts [expr ~-8]
7
The operator reverts all bits of a number 7. One of the bits also determines, whether the number is negative or not. If we negate all the bits one more time, we get number 7 again.
The bitwise and operator performs bit-by-bit comparison between two numbers. The result for a bit position is 1 only if both corresponding bits in the operands are 1.
      00110
& 00011
= 00010
The first number is a binary notation of 6. The second is 3. The result is 2.
% puts [expr 6 & 3]
2
% puts [expr 3 & 6]
2
The bitwise or operator performs bit-by-bit comparison between two numbers. The result for a bit position is 1 if either of the corresponding bits in the operands is 1.
     00110
| 00011
= 00111
The result is 00110 or decimal 7.
% puts [expr 6 | 3]
7
% puts [expr 3 | 6]
7
The bitwise exclusive or operator performs bit-by-bit comparison between two numbers. The result for a bit position is 1 if one or the other (but not both) of the corresponding bits in the operands is 1.
      00110
^ 00011
= 00101
The result is 00101 or decimal 5.
% puts [expr 6 ^ 3]
5
% puts [expr 3 ^ 6]
5

Operator precedence

The operator precedence tells us which operators are evaluated first. The precedence level is necessary to avoid ambiguity in expressions.
What is the outcome of the following expression? 28 or 40?
 3 + 5 * 5
Like in mathematics, the multiplication operator has a higher precedence than addition operator. So the outcome is 28.
(3 + 5) * 5
To change the order of evaluation, we can use parentheses. Expressions inside parentheses are always evaluated first.
The following table shows common Tcl operators ordered by precedence (highest precedence first):
Category Symbol Associativity
Sign, bit-wise, logical NOT - + ~ ! Left
Exponentiation ** Left
Arithmetic + - * / % Left
Shift << >> Left
Relational == != < > <= >= Left
String comparison eq ne Left
List in ni Left
Bitwise & | ^ Left
Boolean && || Left
Ternary ?: Right
Operators on the same row of the table have the same precedence.
!/usr/bin/tclsh

puts [expr 3 + 5 * 5]
puts [expr (3 + 5) * 5]

puts [expr ! 1 || 1]
puts [expr ! (1 || 1)]
In this code example, we show some common expressions. The outcome of each expression is dependent on the precedence level.
puts [expr 3 + 5 * 5]
This line prints 28. The multiplication operator has a higher precedence than addition. First the product of 5*5 is calculated. Then 3 is added.
puts [expr (3 + 5) * 5]
Round brackets can be used to change the precedence level. In the above expression, number 3 is added to 5 and the result is multiplied by 5.
puts [expr ! 1 || 1]
In this case, the negation operator has a higher precedence. First, the first true (1) value is negated to false (0), than the || operator combines false and true, which gives true in the end.
$ ./precedence.tcl 
28
40
1
0
Output.

Associativity

Sometimes the precedence is not satisfactory to determine the outcome of an expression. There is another rule called associativity. The associativity of operators determines the order of evaluation of operators with the sameprecedence level.
9 / 3 * 3
What is the outcome of this expression? 9 or 1? The multiplication, deletion and the modulo operator are left to right associated. So the expression is evaluated this way: (9 / 3) * 3 and the result is 9.
Arithmetic, boolean, relational and bitwise operators are all left to right associated.
The ternary operator is right associated.

The ternary operator

The ternary operator (?:) is a conditional operator. It is a convenient operator for cases, where we want to pick up one of two values, depending on the conditional expression.
cond-exp ? exp1 : exp2
If cond-exp is true, exp1 is evaluated and the result is returned. If the cond-exp is false, exp2 is evaluated and its result is returned.
#!/usr/bin/tclsh

set age 32
set adult [expr $age >= 18 ? true : false]

puts "Adult: $adult"
In most countries the adulthood is based on your age. You are adult if you are older than a certain age. This is a situation for a ternary operator.
set adult [expr $age >= 18 ? true : false]
First the expression on the right side of the assignment operator is evaluated. The first phase of the ternary operator is the condition expression evaluation. So if the age is greater or equal to 18, the value following the ? character is returned. If not, the value following the : character is returned. The returned value is then assigned to the adult variable.
$ ./ternary.tcl
Adult: true
A 32 years old person is adult.

Calculating prime numbers

We are going to calculate prime numbers. Some of the features (lists, loops) will be covered later in the tutorial.
#!/usr/bin/tclsh

set nums { 1 2 3 4 5 6 7 8 9 10 11 12 13 14
15 16 17 18 19 20 21 22 23 24
}

puts "Prime numbers"

foreach num $nums {

if { $num==1 || $num==2 || $num==3 } {

puts -nonewline "$num "
continue
}

set i [expr int(sqrt($num))]
set isPrime true

while { $i > 1 } {

if { $num % $i == 0 } {

set isPrime false
}

incr i -1
}

if { $isPrime } {

puts -nonewline "$num "
}
}

puts ""
In the above example, we deal with many various operators. A prime number (or a prime) is a natural number that has exactly two distinct natural number divisors: 1 and itself. We pick up a number and divide it by numbers, from 1 up to the picked up number. Actually, we don't have to try all smaller numbers, we can divide by numbers up to the square root of the chosen number. The formula will work. We use the remainder division operator.
set nums { 1 2 3 4 5 6 7 8 9 10 11 12 13 14 
15 16 17 18 19 20 21 22 23 24
}
We will calculate primes from this list of numbers.
if { $num==1 || $num==2 || $num==3 } {

puts -nonewline "$num "
continue
}
We skip the calculations for the 1, 2, 3 numbers. They are primes. Note the usage of the equality and conditional or operators. The == has a higher precedence than the || operator. So we don't need to use parentheses.
set i [expr int(sqrt($num))]
We are OK if we only try numbers smaller than the square root of a number in question.
while { $i > 1 } {

if { $num % $i == 0 } {

set isPrime false
}

incr i -1
}
This is a while loop. The i is the calculated square root of the number. We use the incr command to to decrease the i by one each loop cycle. When the i is smaller than 1, we terminate the loop. For example, we have number 9. The square root of 9 is 3. We will divide the 9 number by 3 and 2. This is sufficient for our calculation.
if { $isPrime } {

puts -nonewline "$num "
}
This is the core of the algorithm. If the remainder division operator returns 0 for any of the i values, than the number in question is not a prime.
$ ./prime.tcl
Prime numbers
1 2 3 5 7 11 13 17 19 23
Output of the script.
In this part of the Tcl tutorial, we covered expressions.
Continue Reading

Basic commands in Tcl programming

Basic commands in Tcl

In this part of the Tcl tutorial, we will cover some basic Tcl commands.
In the first example, we will mention the puts command. The puts command is used to print messages to the console or to other channels like a file. The command has the following syntax:
puts ?-nonewline? ?channelId? string
The puts is the command name. Optional parameters are specified between question marks. The -nonewline switch suppresses the newline character. By default, the command puts a newline to each message. The channelId must be an identifier for an open channel such as the Tcl standard input channel (stdin), the return value from an invocation of open or socket. It defaults to stdout, if not specified. Finally the string is the message to be printed.
#!/usr/bin/tclsh

puts "This is Tcl tutorial"
puts stdout "This is Tcl tutorial"
The puts command prints a message to the console. Both command invocations do the same thing.
#!/usr/bin/tclsh

puts [open messages w] "This is Tcl tutorial"
Here we use the puts command to write to a file. We open a file for writing using the open command.
$ cat messages 
This is Tcl tutorial
We show the contents of the messages file created by the above Tcl script.

Greeting a user.
#!/usr/bin/tclsh

puts -nonewline "What is your name? "
flush stdout
gets stdin name
puts "Hello $name"
In this example, we request an input from the user and print the input in a custom greeting.
puts -nonewline "What is your name? "
The -nonewline option suppresses the newline. The prompt remains on the same line.
flush stdout
The output is buffered. To see the output immediately after the command runs, we can use the flush command. The stdoutis the standard output. In our case a terminal. It is called a channel id in Tcl.
gets stdin name
The gets command reads a line from the standard input. The result is stored in the name variable.
puts "Hello $name"
Finally, we greet the user.
$ ./name.tcl 
What is your name? Jan
Hello Jan
Running the example.

The info command returns information about the state of the Tcl interpreter.
#!/usr/bin/tclsh

puts [info tclversion]
puts [info host]
puts [info exists var]
The info command has several options. We show three of them.
puts [info tclversion]
Here we print the version of the Tcl interpreter.
puts [info host]
This line prints the host name.
puts [info exists var]
Finally we check if the variable var is set.

The set command is used to create and read variables. The unset command destroys a variable.
#!/usr/bin/tclsh

set x 23
puts $x
puts [set x]

unset x
puts [info exists x]
An example showing the set and unset commands.
set x 23
We create an x variable and assign a value 23 to it.
puts $x
We print the value of the x variable.
puts [set x]
This line also prints the value of the x variable. The set command with one parameter reads the value of the variable. The value is passed to the putscommand and printed to the terminal.
unset x
The variable x is destroyed.
puts [info exists x]
We verify the existence of the variable using the info existscommand.

Tcl scripts like any other scripts can take command line arguments. Tcl has three predefined variables.
  • $argc - the number of arguments passed to the script
  • $argv - the list of arguments
  • $argv0 - the name of the script
#!/usr/bin/tclsh

puts "The script has $argc arguments"
puts "The list of arguments: $argv"
puts "The name of the script is $argv0"
We use all the predefined variables in this script.
$ ./args.tcl 1 2 3 
The script has 3 arguments
The list of arguments: 1 2 3
The name of the script is ./args.tcl
Running the example.
This chapter covered some basics of the Tcl language.
Continue Reading

Lexical structure of Tcl Programming Language

Lexical+structure+of+Tcl+Programming+Language

Tcl lexical structure

Computer languages, like human languages, have a lexical structure. A lexis of a Tcl language consists of basic elements and rules that apply to them. Words are basic elements in Tcl. Words can be either commands or command arguments. Substitution is one of the basic rules of the Tcl grammar.

Commands

Tcl is a string-based, interpreted command language. A Tcl script consists of commands, which are separated by newlines or semicolons. Commands are the basic execution elements. A command is followed by one or more words which are its arguments. Each argument is separated by white space.
A Tcl command has the following form : command arg1 arg2 arg3 ...The Tcl interpreter takes each word of the sentence and evaluates it. The first word is considered to be the command. Most Tcl commands are variadic. This means that they can process variable number of arguments.
When a Tcl script is parsed the commands are evaluated. Each command interprets words in its own context.
puts "Tcl language"
In the above code excerpt, we have a puts command. This command prints a message to the console. The "Tcl language" is a string, which is being printed. Unlike in other languages, strings must not be enclosed in double quotes. Unless there is a white space.
#!/usr/bin/tclsh

puts zetcode.com; puts androida.co

puts zetcode
puts androida
In the first case the commands are separated by the semicolon (;) character. In the second case they are separated by the newline character.

Substitution

There are three kinds of substitutions in Tcl.
  • Command substitution
  • Variable substitution
  • Backslash substitution
Square brackets are used for command substitution.
% puts [expr 1+2]
3
The expr command is used to perform arithmetic calculations. First the command between the square brackets is evaluated and the result is returned to the puts command. The puts command then evaluates the result and prints it to the console.

If a word contains a dollar sign ($), then Tcl performs variable substitution. The dollar-sign and the following characters are replaced in the word by the value of a variable.
#!/usr/bin/tclsh

set name Jane

puts name
puts $name
We create a variable called name and set a value to it.
puts name
In this case, we print a string "name" to the console.
puts $name
In the second case, the argument is preceded by a $ character. The value of the name variable is printed to the console.
$ ./name.tcl 
name
Jane
Output of the example.

With the backslash substitution, we escape the original meaning of the character. For example, the \n stands for a new line. The \t is the tab character.
% puts "This is \t Sparta"
This is Sparta
Here the \t sequence is replaced with a tab.
#!/usr/bin/tclsh

puts "This was a \"great\" experience"
puts "The \\ character is the backslash character"

puts "20000\b\b miles"
We use the backslash substitution, if we want to have quotes inside quote characters. Also if we want to print the \ character, we must precede it with additional backslash. The \b is substituted with a backspace.
$ ./backslash.tcl 
This was a "great" experience
The \ character is the backslash character
200 miles
Running the example.

Comments

Comments are used by humans to clarify the source code. In Tcl comments start with the # character.
# example of a puts command
puts "Tcl language"
All characters after the # character are ignored by tclsh.
puts "Tcl language" ; # example of a puts command
Inline comments are possible only if we use a semicolon.

White space

White space is used to separate words in Tcl source. It is also used to improve readability of the source code.
set name Jane
The set command takes two parameters, which are separated by white space.
set age        32
set name Robert
set occupation programmer
We might use more spaces if we want to improve the clarity of the source code.
set vals { 1 2 3 4 5 6 7 }
puts $vals
White space is used to separate items in Tcl lists. In C based languages, we would use the comma character.

Variables

A variable is an identifier, which holds a value. In programming we say, that we assign/set a value to a variable. Technically speaking, a variable is a reference to a computer memory, where the value is stored. Variable names are case sensitive. This means, that Name, name or NAME refer to three different variables.
Variables in Tcl are created with the set command. To obtain the value of a variable, its name is preceded with a $ character.
#!/usr/bin/tclsh

set name Jane
set Name Julia
set NAME Erika

puts $name
puts $Name
puts $NAME
In the above script we set three variables. The variable names are the same, they only differ in case. This practice is however not recommended.
$ ./case.tcl 
Jane
Julia
Erika
Output.

Braces

Braces {} have special meaning in Tcl. Substitution of words is disabled inside braces.
#!/usr/bin/tclsh

set name {Julia Novak}
puts $name

puts "Her name is $name"
puts {Her name is $name}
This is a small script showing a usage of the braces in Tcl.
set name {Julia Novak}
Braces can be used instead of double quotes to set strings separated by a white space.
puts "Her name is $name"
Here the variable is substituted.
puts {Her name is $name}
When using braces, the variable is not substituted. Everything is printed literally.
$ ./braces.tcl 
Julia Novak
Her name is Julia Novak
Her name is $name
Output of the braces.tcl script.

#!/usr/bin/tclsh


set numbers { 1 2 3 4 5 6 7 }
puts $numbers

puts "Braces {} are reserved characters in Tcl"
puts {Braces {} are reserved characters in Tcl}
Braces are used to create lists. A list is a basic data type in Tcl.
set numbers { 1 2 3 4 5 6 7 }
Here a list of numbers is created.
puts "Braces {} are reserved characters in Tcl"
puts {Braces {} are reserved characters in Tcl}
Braces inside double quotes or inside other braces are taken as regular characters without special meaning.
$ ./braces2.tcl 
1 2 3 4 5 6 7
Braces {} are reserved characters in Tcl
Braces {} are reserved characters in Tcl
Output of the braces2.tcl script.

Square brackets

Square brackets, [], are used to create nested commands. These nested commands are executed before the main command on the Tcl source line. They are used to pass the result of one command as an argument to another command.
#!/usr/bin/tclsh

set cwd [pwd]
puts $cwd

puts [clock format [clock seconds] -format "%Y-%m-%d %T"]
In the above code example, we show some nested commands.
set cwd [pwd]
The pwd command returns the current working directory of the script. It is put between the square brackets, which makes it a nested command. First the pwd command is executed and then the result of the command is set to the cwd variable.
puts [clock format [clock seconds] -format "%Y-%m-%d %T"]
Nested commands can be nested inside other nested commands. First the clock seconds is executed. It returns the current local time in seconds. The result is passed to the clock format command, which formats the time in a readable form. Finally, the formatted time is returned to the puts command, which prints it to the console.
$ ./nested.tcl 
/home/vronskij/programming/tcl/lexis
2011-04-05 12:19:21
Output of the example.

Quotes

Double quotes group words as a single argument to commands. Dollar signs, square brackets and backslash are interpreted inside quotes.
#!/usr/bin/tclsh

set distro Ubuntu
puts "The Linux distribution name is $distro"

puts "The current working directory: [pwd]"
puts "2000000\b\b\b miles"
This is a practical example of using quotes in Tcl.
puts "The Linux distribution name is $distro"
The variable distro is evaluated inside the quote characters. The $distro is replaced with "Ubuntu".
puts "The current working directory: [pwd]"
Commands inside square brackets are interpreted too. Here we get the current working directory with the pwd command.
puts "2000000\b\b\b miles"
The \b escape sequence deletes a preceding character. In our case three zeros are deleted.
$ ./quotes.tcl 
The Linux distribution name is Ubuntu
The current working directory: /home/vronskij/programming/tcl/lexis
2000 miles
Output of the quotes.tcl example.

Backslash

The backslash character can be used in three different ways in Tcl. It introduces some special characters, called escape sequences. These can be newlines, tabs, backspaces among others. It escapes the meaning of special Tcl characters ($, {}, "", \, ()). Finally, it can serve as a line continuation character.
#!/usr/bin/tclsh

puts "0\t1"

set name Jane
puts \$name
puts \\$name

puts "He said: \"There are plenty of them\""
puts "There are currently many Linux\
distributions in the world"
The above script shows how the backslash character can be used in Tcl.
puts "0\t1"
The \t character has a special meaning in Tcl. It stands for a tab white space character. When we execute the script, 8 spaces are put inside 0 and 1.
puts \$name
With the backslash, we escape the meaning of the dollar sign. In our case $name characters are printed to the console.
puts \\$name
The backslash can be escaped too. Here the backslash character and the value of the name variable are printed to the console.
puts "He said: \"There are plenty of them\""
We can form direct speech by escaping the meaning of the inner double quotes.
puts "There are currently many Linux\
distributions in the world"
If the source line is too wide, we can continue on the next line using the backslash character. Effectively escaping the newline.
$ ./backslash.tcl 
0 1
$name
\Jane
He said: "There are plenty of them"
There are currently many Linux distributions in the world
Running the example.

Round brackets

Round brackets are used to indicate an array subscript or to change the precedence of operators for the exprcommand.
#!/usr/bin/tclsh

set names(1) Jane
set names(2) Robert

puts $names(1)
puts $names(2)

puts [expr (1+3)*5]
This is a simple example with round brackets in Tcl.
puts $names(1)
We use the round brackets to access the value by a key which is specified inside round brackets.
puts [expr (1+3)*5]
Here we change the precedence for operators. First 1 and 3 are added and then the result is multiplied by 5.
In this chapter we have described the lexis of the Tcl language.
Continue Reading