TCL Tutorial 1
TCL Tutorial 1
Tcl Tutorial
1. Introduction
2. Running Tcl
3. Simple Text Output
4. Assigning values to variables
5. Evaluation & Substitutions 1: Grouping arguments with ""
6. Evaluation & Substitutions 2: Grouping arguments with {}
7. Evaluation & Substitutions 3: Grouping arguments with []
8. Results of a command - Math 101
9. Computers and Numbers
10. Numeric Comparisons 101 - if
11. Textual Comparison - switch
12. Looping 101 - While loop
13. Looping 102 - For and incr
14. Adding new commands to Tcl - proc
15. Variations in proc arguments and return values
16. Variable scope - global and upvar
17. Tcl Data Structures 101 - The list
18. Adding & Deleting members of a list
19. More list commands - lsearch, lsort, lrange
20. Simple pattern matching - "globbing"
21. String Subcommands - length index range
22. String comparisons - compare match first last wordend
23. Modifying Strings - tolower, toupper, trim, format
24. Regular Expressions 101
25. More Examples Of Regular Expressions
26. More Quoting Hell - Regular Expressions 102
27. Associative Arrays
28. More On Arrays - Iterating and use in procedures
29. Dictionaries
30. File Access 101
31. Information about Files - file, glob
32. Invoking Subprocesses from Tcl - exec, open
33. Learning the existence of commands and variables ? - info
34. State of the interpreter - info
35. Information about procs - info
36. Modularization - source
37. Building reusable libraries - packages and namespaces
38. Creating Commands - eval
39. More command construction - format, list
40. Substitution without evaluation - format, subst
41. Changing Working Directory - cd, pwd
42. Debugging & Errors - errorInfo errorCode catch error return
43. More Debugging - trace
44. Command line arguments and environment strings
45. Leftovers - time, unset
46. Channel I/O: socket, fileevent, vwait
47. Time and Date - clock
48. More channel I/O - fblocked & fconfigure
49. Child interpreters
https://www.tcl.tk/man/tcl8.5/tutorial/tcltutorial.html 1/1
9/11/2017 Introduction
Introduction
Welcome to the Tcl tutorial. We wrote it with the goal of helping you to learn Tcl. It
is aimed at those who have some knowledge of programming, although you certainly
don't have to be an expert. The tutorial is intended as a companion to the Tcl
manual pages which provide a reference for all Tcl commands.
It is divided into brief sections covering different aspects of the language. Depending
on what system you are on, you can always look up the reference documentation for
commands that you are curious about. On Unix for example, man while would bring up
the man page for the while command.
Each section is accompanied by relevant examples showing you how to put to use
the material covered.
Additional Resources
The Tcl community is an exceedingly friendly one. It's polite to try and figure things
out yourself, but if you're struggling, we're more than willing to help. Here are some
good places to get help:
Credits
Thanks first and foremost to Clif Flynt for making his material available under a BSD
license. The following people also contributed:
Neil Madden
Arjen Markus
David N. Welton
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl0.html 1/1
9/11/2017 Running Tcl
Running Tcl
When you have installed Tcl, the program you will then call to utilize it is tclsh. For
instance, if you write some code to a file "hello.tcl", and you want to execute it, you
would do it like so: tclsh hello.tcl. Depending on the version of Tcl installed, and the
operating system distribution you use, the tclsh program may be a link to the real
executable, which may be named tclsh8.6 or tclsh86.exe on Microsoft Windows.
The tclsh is a simple command-line interactive interpreter. You can either start it
with a script on the command line, in which case it runs the script to completion and
then exits, or you can start it without any arguments, in which case you will be
presented with an interactive prompt, usually using a % symbol to prompt for input.
In interactive mode, you can type in commands, which Tcl will then execute and
display the result, or any error messages that result. To exit the interpreter, type
exit and press Return. Playing around with the interactive interpreter is a great way
to learn how to use Tcl. Most Tcl commands will produce a helpful error message
explaining how they are used if you just type in the command with no arguments.
You can get a list of all the commands that your interpreter knows about by typing
info commands.
The tclsh executable is just one way of starting a Tcl interpreter. Another common
executable, which may be installed on your system, is the wish, or WIndowing SHell.
This is a version of Tcl that automatically loads the Tk extension for building
graphical user interfaces (GUIs). This tutorial does not cover Tk, and so we will not
use the wish interpreter here. Other options are also available, providing more
functional environments for developing and debugging code than that provided by
the standard tclsh. One very popular choice is the TkCon enhanced interpreter,
written by Jeff Hobbs. The Eclipse IDE offers good Tcl support, in the form of the
DLTK extension, and the Tcl'ers Wiki offers a list of IDEs with Tcl support and a
comprehensive catalogue of Tcl source code editors. Don't panic, though! If you
don't know how to use a sophisticated development environment, it is still very easy
to write Tcl code by hand in a simple text editor (such as Notepad).
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl0a.html 1/1
9/11/2017 Simple Text Output
The traditional starting place for a tutorial is the classic "Hello, World" program.
Once you can print out a string, you're well on your way to using Tcl for fun and
profit!
A single unit of text after the puts command will be printed to the standard output
device. The default behavior is to print a newline character ("return") appropriate for
the system after printing the text.
If the string has more than one word, you must enclose the string in double quotes
or braces ({}). A set of words enclosed in quotes or braces is treated as a single
unit, while words separated by whitespace are treated as multiple arguments to the
command. Quotes and braces can both be used to group several words into a single
unit. However, they actually behave differently. In the next lesson you'll start to
learn some of the differences between their behaviors. Note that in Tcl, single
quotes are not significant, as they are in other programming languages such as C,
Perl and Python.
Many commands in Tcl (including puts) can accept multiple arguments. If a string is
not enclosed in quotes or braces, the Tcl interpreter will consider each word in the
string as a separate argument, and pass each individually to the puts command. The
puts command will try to evaluate the words as optional arguments. This will
probably result in an error.
Example
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl1.html 1/1
9/11/2017 Assigning values to variables
it places the second argument (Cauliflower) in the memory space referenced by the
first argument (fruit). Set always returns the contents of the variable named in the
first argument. Thus, when set is called with two arguments, it places the second
argument in the memory space referenced by the first argument and then returns
the second argument. In the above example, for instance, it would return
"Cauliflower", without the quotes.
The first argument to a set command can be either a single word, like fruit or pi , or
it can be a member of an array. Arrays will be discussed in greater detail later, for
the time being just remember that many data can be collected under a single
variable name, and an individual datum can be accessed by its index within that
array. Indexing into an array in Tcl is handled by putting the index within
parentheses after the name of the variable.
Setcan also be invoked with only one argument. When called with just one
argument, it will return the contents of that argument.
If you look at the example code, you'll notice that in the set command the first
argument is typed with only its name, but in the puts statement the argument is
preceded with a $.
The dollar sign tells Tcl to use the value of the variable - in this case X or Y.
Tcl passes data to subroutines either by name or by value. Commands that don't
change the contents of a variable usually have their arguments passed by value.
Commands that do change the value of the data must have the data passed by
name.
Example
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl2.html 1/2
9/11/2017 Assigning values to variables
set Y 1.24
puts $X
puts $Y
puts "..............................."
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl2.html 2/2
9/11/2017 Evaluation & Substitutions 1: Grouping arguments with ""
This lesson is the first of three which discuss the way Tcl handles substitution during
command evaluation.
In Tcl, the evaluation of a command is done in 2 phases. The first phase is a single
pass of substitutions. The second phase is the evaluation of the resulting command.
Note that only one pass of substitutions is made. Thus in the command
puts $varName
the contents of the proper variable are substituted for $varName, and then the
command is executed. Assuming we have set varName to "Hello World", the sequence
would look like this: puts $varName ⇒ puts "Hello World", which is then executed and
prints out Hello World.
A command within square brackets ([]) is replaced with the result of the execution
of that command. (This will be explained more fully in the lesson "Results of a
Command - Math 101.")
Words within double quotes or braces are grouped into a single argument. However,
double quotes and braces cause different behavior during the substitution phase. In
this lesson, we will concentrate on the behavior of double quotes during the
substitution phase.
Grouping words within double quotes allows substitutions to occur within the
quotations - or, in fancier terms, "interpolation". The substituted group is then
evaluated as a single argument. Thus, in the command:
puts "The current stock value is $varName"
the current contents of varName are substituted for $varName, and then the entire
string is printed to the output device, just like the example above.
In general, the backslash (\) disables substitution for the single character
immediately following the backslash. Any character immediately following the
backslash will stand without substitution.
However, there are specific "Backslash Sequence" strings which are replaced by
specific values during the substitution phase. The following backslash strings will be
substituted as shown below.
The final exception is the backslash at the end of a line of text. This causes the
interpreter to ignore the newline, and treat the text as a single line of text. The
interpreter will insert a blank space at the location of the ending backslash.
Example
set Z Albany
set Z_LABEL "The Capitol of New York is: "
set a 100.00
puts "Washington is not on the $a bill" ;# This is not what you want
puts "Lincoln is not on the $$a bill" ;# This is OK
puts "Hamilton is not on the \$a bill" ;# This is not what you want
puts "Ben Franklin is on the \$$a bill" ;# But, this is OK
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl3.html 2/2
9/11/2017 Evaluation & Substitutions 2: Grouping arguments with {}
During the substitution phase of command evaluation, the two grouping operators,
the brace ({) and the double quote ("), are treated differently by the Tcl interpreter.
In the last lesson you saw that grouping words with double quotes allows
substitutions to occur within the double quotes. By contrast, grouping words within
double braces disables substitution within the braces. Characters within braces are
passed to a command exactly as written. The only "Backslash Sequence" that is
processed within braces is the backslash at the end of a line. This is still a line
continuation character.
Note that braces have this effect only when they are used for grouping (i.e. at the
beginning and end of a sequence of words). If a string is already grouped, either
with quotes or braces, and braces occur in the middle of the grouped string (i.e.
"foo{bar"), then the braces are treated as regular characters with no special
meaning. If the string is grouped with quotes, substitutions will occur within the
quoted string, even between the braces.
Example
set Z Albany
set Z_LABEL "The Capitol of New York is: "
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl4.html 1/1
9/11/2017 Evaluation & Substitutions 3: Grouping arguments with []
You obtain the results of a command by placing the command in square brackets
([]). This is the functional equivalent of the back single quote (`) in sh
programming, or using the return value of a function in C.
As the Tcl interpreter reads in a line it replaces all the $variables with their values. If
a portion of the string is grouped with square brackets, then the string within the
square brackets is evaluated as a command by the interpreter, and the result of the
command replaces the square bracketed string.
The parser scans the entire command, and sees that there is a command
substitution to perform: readsensor [selectsensor] , which is sent to the interpreter
for evaluation.
The parser once again finds a command to be evaluated and substituted,
selectsensor
The fictitious selectsensor command is evaluated, and it presumably returns a
sensor to read.
At this point, readsensor has a sensor to read, and the readsensor command is
evaluated.
Finally, the value of readsensor is passed on back to the puts command, which
prints the output to the screen.
Example
set x abc
puts "A simple substitution: $x\n"
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl5.html 2/2
9/11/2017 Results of a command - Math 101
The Tcl command for doing math type operations is expr. The following discussion of
the expr command is extracted and adapted from the expr man page. Many
commands use expr behind the scenes in order to evaluate test expressions, such as
if, while and for loops, discussed in later sections. All of the advice given here for expr
also holds for these other commands.
exprtakes all of its arguments ("2 + 2" for example) and evaluates the result as a Tcl
"expression" (rather than a normal command), and returns the value. The operators
permitted in Tcl expressions include all the standard math functions, logical
operators, bitwise operators, as well as math functions like rand(), sqrt(), cosh() and
so on. Expressions almost always yield numeric results (integer or floating-point
values).
Performance tip: enclosing the arguments to expr in curly braces will result in
faster code. So do expr {$i * 10} instead of simply expr $i * 10
WARNING: You should always use braces when evaluating expressions that
may contain user input, to avoid possible security breaches. The expr command
performs its own round of substitutions on variables and commands, so you
should use braces to prevent the Tcl interpreter doing this as well (leading to
double substitution). To illustrate the danger, consider this interactive session:
% set userinput {[puts DANGER!]}
[puts DANGER!]
% expr $userinput == 1
DANGER!
0
% expr {$userinput == 1}
0
In the first example, the code contained in the user-supplied input is evaluated,
whereas in the second the braces prevent this potential danger. As a general
rule, always surround expressions with braces, whether using expr directly or
some other command that takes an expression (such as if or while).
OPERANDS
Note that the octal and hexadecimal conversion takes place differently in the expr
command than in the Tcl substitution phase. In the substitution phase, a \x32
would be converted to an ascii "2", while expr would convert 0x32 to a decimal 50.
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl6.html 1/4
9/11/2017 Results of a command - Math 101
If an operand does not have one of the integer formats given above, then it is
treated as a floating-point number, if that is possible. Floating-point numbers may
be specified in any of the ways accepted by an ANSI-compliant C compiler. For
example, all of the following are valid floating-point numbers:
2.1
3.
6E4
7.91e+16
.000001
Note however, that it does not support numbers of the following forms:
It is possible to deal with numbers in that form, but you will have to convert these
"strings" to numbers in the standard form first.
Beware of leading zeros: 0700 is not interpreted as the decimal number 700 (seven
hundred), but as the octal number 700 = 7*8*8 = 448 (decimal).
% expr {0900+1}
expected integer but got "0900" (looks like invalid octal number)
Octal numbers are in fact a relic of the past, when such number formats were much
more common.
OPERATORS
The valid operators are listed below, grouped in decreasing order of precedence:
-+~!
Unary minus, unary plus, bit-wise NOT, logical NOT. None of these operators
may be applied to string operands, and bit-wise NOT may be applied only to
integers.
**
Exponentiation (works on both floating-point numbers and integers)
*/%
Multiply, divide, remainder. None of these operators may be applied to string
operands, and remainder may be applied only to integers. The remainder will
always have the same sign as the divisor and an absolute value smaller than
the divisor.
+-
Add and subtract. Valid for any numeric operands.
<< >>
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl6.html 2/4
9/11/2017 Results of a command - Math 101
Left and right (bit) shift. Valid for integer operands only.
< > <= >=
Relational operators: less, greater, less than or equal, and greater than or
equal. Each operator produces 1 if the condition is true, 0 otherwise. These
operators may be applied to numeric operands as well as strings, in which case
string comparison is used.
eq ne in ni
compare two strings for equality (eq) or inequality (ne). and two operators for
checking if a string is contained in a list (in) or not (ni). These operators all
return 1 (true) or 0 (false). Using these operators ensures that the operands
are regarded exclusively as strings (and lists), not as possible numbers:
% expr { "9" == "9.0"}
1
% expr { "9" eq "9.0"}
0
&
Bit-wise AND. Valid for integer operands only.
^
Bit-wise exclusive OR. Valid for integer operands only.
|
Bit-wise OR. Valid for integer operands only.
&&
Logical AND. Produces a 1 result if both operands are non-zero, 0 otherwise.
Valid for numeric operands only (integers or floating-point).
||
Logical OR. Produces a 0 result if both operands are zero, 1 otherwise. Valid for
numeric operands only (integers or floating-point).
x?y:z
If-then-else. If x evaluates to non-zero, then the result is the value of y.
Otherwise the result is the value of z. The x operand must have a numeric
value.
% set x 1
% expr { $x>0? ($x+1) : ($x-1) }
2
MATH FUNCTIONS
Tcl supports the following mathematical functions in expressions:
abs acos asin atan
atan2 bool ceil cos
cosh double entier exp
floor fmod hypot int
isqrt log log10 max
min pow rand round
sin sinh sqrt srand
tan tanh wide
Besides these functions, you can also apply commands within an expression. For
instance:
% set x 1
% set w "Abcdef"
% expr { [string length $w]-2*$x }
4
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl6.html 3/4
9/11/2017 Results of a command - Math 101
TYPE CONVERSIONS
Tcl supports the following functions to convert from one representation of a number
to another:
double int wide entier
The next lesson explains the various types of numbers in more detail.
Example
set X 100
set Y 256
set Z [expr {$Y + $X}]
set Z_LABEL "$Y plus $X is "
puts "Because of the precedence rules \"5 + -3 * 4\" is: [expr {-3 * 4 + 5}]"
puts "Because of the parentheses \"(5 + -3) * 4\" is: [expr {(5 + -3) * 4}]"
set A 3
set B 4
puts "The hypotenuse of a triangle: [expr {hypot($A,$B)}]"
#
# The trigonometric functions work with radians ...
#
set pi6 [expr {3.1415926/6.0}]
puts "The sine and cosine of pi/6: [expr {sin($pi6)}] [expr {cos($pi6)}]"
#
# Working with arrays
#
set a(1) 10
set a(2) 7
set a(3) 17
set b 2
puts "Sum: [expr {$a(1)+$a($b)}]"
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl6.html 4/4
9/12/2017 Computers and numbers
If you are new to programming, then this lesson may contain some surprising
information. But even if you are used to writing programs, computers can do
unexpected things with numbers. The purpose of this lesson is to shed some light on
some of the mysteries and quirks you can encounter.
Important note: I used Tcl 8.4.1 for all examples. In Tcl 8.5 the results will hopefully
be more intuitive, as a result of adding so-called big integers. Nevertheless, the
general theme remains the same.
Now consider the following example, it is almost the same, with the exception of a
decimal dot:
The reason is simple, well if you know more about the background of computer
arithmetic:
In the first example we multiplied two integer numbers, or short integers. While
we are used to these numbers ranging from -infinity to +infinity, computers can
not deal with that range (at least not that easily). So, instead, computers deal
with a subset of the actual mathematical integer numbers. They deal with
numbers from -231 to 231-1 (in general) - that is, with numbers from
-2147483648 to 2147483647.
Numbers outside that range can not be dealt with that easily. This is also true
of the results of a computation (or the intermediate results of a computation,
even if the final result does fit).
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl6a.html 1/4
9/12/2017 Computers and numbers
Because the range is so much bigger, in the second example the result falls
within the limits and we get the answer we expected.
Tcl's strategy
Tcl uses a simple but efficient strategy to decide what kind of numbers to use for the
computations:
If you add, subtract, multiply and divide two integer numbers, then the result is
an integer. If the result fits within the range you have the exact answer. If not,
you end up with something that appears to be completely wrong. (Note: not
too long ago, floating-point computations were much more time-consuming
than integer computations. And most computers do not warn about integer
results outside the range, because that is too time-consuming too: a computer
typically uses lots of such operations, most of which do fit into the designated
range.)
If you add, subtract, multiply and divide an integer number and a floating-point
number, then the integer number is first converted to a floating-point number
with the same value and then the computation is done, resulting in a floating-
point number.
Floating-point computations are quite complex, and the current (IEEE) standard
prescribes what should happen in minute detail. One such detail is that results
outside the proper ranges are reported. Tcl catches these and displays a
warning:
# Compute 1.0e+300/1.0-300
% puts [expr {1.0e300/1.0e-300}]
floating-point value too large to represent
Now some of the mysteries you can find yourself involved in. Run the following
scripts:
#
# Division
#
puts "1/2 is [expr {1/2}]"
puts "-1/2 is [expr {-1/2}]"
puts "1/2 is [expr {1./2}]"
puts "1/3 is [expr {1./3}]"
puts "1/3 is [expr {double(1)/3}]"
The first two computations have the surprising result: 0 and -1. That is because the
result is an integer number and the mathematically exact results 1/2 and -1/2 are
not.
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl6a.html 2/4
9/12/2017 Computers and numbers
If you interested in the details of how Tcl works, the outcome q is determined as
follows:
a = q * b + r
0 <= |r| < |b|
r has the same sign as q
While many of the above computations give the result you would expect, note
however the last decimals, the last two do not give exactly 5 and 12! This is because
computers can only deal with numbers with a limited precision: floating-point
numbers are not our mathematical real numbers.
The fact that floating-point numbers are not ordinary decimal or real numbers and
the actual way computers deal with floating-point numbers, has a number of
consequences:
Results obtained on one computer may not exactly match the results on
another computer. Usually the differences are small, but if you have a lot of
computations, they can add up!
Whenever you convert from floating-point numbers to integer numbers, for
instance when determining the labels for a graph (the range is 0 to 1.2 and you
want a stepsize of 0.1), you need to be careful:
#
# The wrong way
#
set number [expr {int(1.2/0.1)}] ;# Force an integer -
;# accidentally number = 11
#
# A right way - note the limit
#
set x 0.0
set delta 0.1
while { $x < 1.2+0.5*$delta } {
... create label $x
set x [expr {$x + $delta}]
}
If you want to do financial computations, take care: there are specific standards
for doing such computations that unfortunately depend on the country where
they are used - the US standard is slightly different from the European
standard.
Transcendental functions, like sin() and exp() are not standardised at all. The
outcome could differ in one or more decimals from one computer to the next.
So, if you want to be absolutely certain that π (pi) is a specific value, use that
value and do not rely on formulae like these:
#
# Two different estimates of "pi" - on Windows 98
#
set pi1 [expr {4.0*atan(1.0)}]
set pi2 [expr {6.0*asin(0.5)}]
puts [expr {$pi1-$pi2}]
-4.4408920985006262e-016
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl6a.html 4/4
9/12/2017 Numeric Comparisons 101 - if
if expr1 ?then? body1 elseif expr2 ?then? body2 elseif ... ?else? ?bodyN?
The words then and else are optional, although generally then is left out and else is
used.
The test expression following if should return a value that can be interpreted as
representing "true" or "false":
False True
a numeric value 0 all others
yes/no no yes
true/false false true
If the test expression returns a string "yes"/"no" or "true"/"false", the case of the
return is not checked. True/FALSE or YeS/nO are legitimate returns.
If the test expression evaluates to False, then the word after body1 will be examined.
If the next word is elseif, then the next test expression will be tested as a condition.
If the next word is else then the final body will be evaluated as a command.
The test expression following the word if is evaluated in the same manner as in the
expr command.
Note: This extra round can cause unexpected trouble - avoid it.
Example
set x 1
if {$x != 1} {
puts "$x is != 1"
} else {
puts "$x is 1"
}
#
# Be careful, this is just an example
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl7.html 1/2
9/12/2017 Numeric Comparisons 101 - if
#
# A dangerous example: due to the extra round of substitution,
# the script stops
#
set y {[exit]}
if "$$y != 1" {
puts "$$y is != 1"
} else {
puts "$$y is 1"
}
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl7.html 2/2
9/12/2017 Textual Comparison - switch
The switch command allows you to choose one of several options in your code. It is
similar to switch in C, except that it is more flexible, because you can switch on
strings, instead of just integers. The string will be compared to a set of patterns, and
when a pattern matches the string, the code associated with that pattern will be
evaluated.
It's a good idea to use the switch command when you want to match a variable
against several possible values, and don't want to do a long series of if... elseif ...
elseif statements.
- or -
String is the string that you wish to test, and pattern1, pattern2, etc are the patterns
that the string will be compared to. If string matches a pattern, then the code within
the body associated with that pattern will be executed. The return value of the body
will be returned as the return value of the switch statement. Only one pattern will be
matched.
If the last pattern argument is the string default, that pattern will match any string.
This guarantees that some set of code will be executed no matter what the contents
of string are.
If there is no default argument, and none of the patterns match string, then the switch
command will return an empty string.
If you use the brace version of this command, there will be no substitutions done on
the patterns. The body of the command, however, will be parsed and evaluated just
like any other command, so there will be a pass of substitutions done on that, just
as will be done in the first syntax. The advantage of the second form is that you can
write multiple line commands more readably with the brackets.
Note that you can use braces to group the body argument when using the switch or if
commands. This is because these commands pass their body argument to the Tcl
interpreter for evaluation. This evaluation includes a pass of substitutions just as it
does for code not within a command body argument.
Example
set x "ONE"
set y 1
set z ONE
switch $x {
"$z" {
set y1 [expr {$y+1}]
puts "MATCH \$z. $y + $z is $y1"
}
ONE {
set y1 [expr {$y+1}]
puts "MATCH ONE. $y + one is $y1"
}
TWO {
set y1 [expr {$y+2}]
puts "MATCH TWO. $y + two is $y1"
}
THREE {
set y1 [expr {$y+3}]
puts "MATCH THREE. $y + three is $y1"
}
default {
puts "$x is NOT A MATCH"
}
}
switch $x "$z" {
set y1 [expr {$y+1}]
puts "MATCH \$z. $y + $z is $y1"
} ONE {
set y1 [expr {$y+1}]
puts "MATCH ONE. $y + one is $y1"
} TWO {
set y1 [expr {$y+2}]
puts "MATCH TWO. $y + two is $y1"
} THREE {
set y1 [expr {$y+3}]
puts "MATCH THREE. $y + three is $y1"
} default {
puts "$x does not match any of these choices"
}
switch $x "ONE" "puts ONE=1" "TWO" "puts TWO=2" "default" "puts NO_MATCH"
switch $x \
"ONE" "puts ONE=1" \
"TWO" "puts TWO=2" \
"default" "puts NO_MATCH";
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl8.html 2/2
9/12/2017 Looping 101 - While loop
Tcl includes two commands for looping, the while and for commands. Like the if
statement, they evaluate their test the same way that the expr does. In this lesson
we discuss the while command, and in the next lesson, the for command. In most
circumstances where one of these commands can be used, the other can be used as
well.
The while command evaluates test as an expression. If test is true, the code in body is
executed. After the code in body has been executed, testis evaluated again.
A continue statement within body will stop the execution of the code and the test will
be re-evaluated. A break within body will break out of the while loop, and execution
will continue with the next line of code after body
Look at the two loops in the example. If it weren't for the break command in the
second loop, it would loop forever.
Example
set x 1
# The next example shows the difference between ".." and {...}
# How many times does the following loop run? Why does it not
# print on each pass?
set x 0
while "$x < 5" {
set x [expr {$x + 1}]
if {$x > 7} break
if "$x > 3" continue
puts "x is $x"
}
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl9.html 2/2
9/12/2017 Looping 102 - For and incr
Tcl supports an iterated loop construct similar to the for loop in C. The for command
in Tcl takes four arguments; an initialization, a test, an increment, and the body of
code to evaluate on each pass through the loop. The syntax for the for command is:
During evaluation of the for command, the start code is evaluated once, before any
other arguments are evaluated. After the start code has been evaluated, the test is
evaluated. If the test evaluates to true, then the body is evaluated, and finally, the
next argument is evaluated. After evaluating the next argument, the interpreter loops
back to the test, and repeats the process. If the test evaluates as false, then the loop
will exit immediately.
Start is the initialization portion of the command. It is usually used to initialize the
iteration variable, but can contain any code that you wish to execute before the loop
starts.
The test argument is evaluated as an expression, just as with the expr while and if
commands.
Nextis commonly an incrementing command, but may contain any command which
the Tcl interpreter can evaluate.
Since you commonly do not want the Tcl interpreter's substitution phase to change
variables to their current values before passing control to the for command, it is
common to group the arguments with curly braces. When braces are used for
grouping, the newline is not treated as the end of a Tcl command. This makes it
simpler to write multiple line commands. However, the opening brace must be on
the line with the for command, or the Tcl interpreter will treat the close of the next
brace as the end of the command, and you will get an error. This is different than
other languages like C or Perl, where it doesn't matter where you place your braces.
Within the body code, the commands break and continue may be used just as they are
used with the while command. When a break is encountered, the loop exits
immediately. When a continue is encountered, evaluation of the body ceases, and the
test is re-evaluated.
This command adds the value in the second argument to the variable named in the
first argument. If no value is given for the second argument, it defaults to 1.
Example
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl10.html 1/2
9/12/2017 Looping 102 - For and incr
puts "Start"
set i 0
while {$i < 10} {
puts "I inside third loop: $i"
incr i
puts "I after incr: $i"
}
set i 0
incr i
# This is equivalent to:
set i [expr {$i + 1}]
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl10.html 2/2
9/12/2017 Adding new commands to Tcl - proc
The proc command creates a new command. The syntax for the proc command is:
When proc is evaluated, it creates a new command with name name that takes
arguments args. When the procedure name is called, it then runs the code contained in
body.
Argsis a list of arguments which will be passed to name. When name is invoked, local
variables with these names will be created, and the values to be passed to name will
be copied to the local variables.
The value that the body of a proc returns can be defined with the return command.
The return command will return its argument to the calling program. If there is no
return, then body will return to the caller when the last of its commands has been
executed. The return value of the last command becomes the return value of the
procedure.
Example
proc for {a b c} {
puts "The for command has been replaced by a puts";
puts "The arguments were: $a\n$b\n$c\n"
}
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl11.html 1/1
9/12/2017 Variations in proc arguments and return values
A proc can be defined with a set number of required arguments (as was done with
sum in the previous lesson, or it can have a variable number of arguments. An
argument can also be defined to have a default value.
Variables can be defined with a default value by placing the variable name and the
default within braces within args. For example:
Since there are default arguments for the b and c variables, you could call the
procedure one of three ways: justdoit 10, which would set a to 10, and leave b set to
its default 1, and c at -1. justdoit 10 20 would likewise set b to 20, and leave C to its
default. Or call it with all three parameters set to avoid any defaults.
A proc will accept a variable number of arguments if the last declared argument is
the word args. If the last argument to a proc argument list is args, then any
arguments that aren't already assigned to previous variables will be assigned to args.
The example procedure below is defined with three arguments. At least one argument
*must* be present when example is called. The second argument can be left out, and
in that case it will default to an empty string. By declaring args as the last argument,
example can take a variable number of arguments.
Note that if there is a variable other than args after a variable with a default, then
the default will never be used. For example, if you declare a proc such as:
proc function { a {b 1} c} {...}, you will always have to call it with 3 arguments.
Tcl assigns values to a proc's variables in the order that they are listed in the
command. If you provide 2 arguments when you call function they will be assigned to
a and b, and Tcl will generate an error because c is undefined.
You can, however, declare other arguments that may not have values as coming
after an argument with a default value. For example, this is valid:
In this case, example requires one argument, which will be assigned to the variable
required. If there are two arguments, the second arg will be assigned to default1. If
there are 3 arguments, the first will be assigned to required, the second to default1,
and the third to default2. If example is called with more than 3 arguments, all the
arguments after the third will be assigned to args.
Example
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl12.html 1/2
9/12/2017 Variations in proc arguments and return values
return 1
} else {
if {$args eq ""} {
puts "There are two arguments - $first and $second"
return 2
} else {
puts "There are many arguments - $first and $second and $args"
return "many"
}
}
}
puts "The example was called with $count1, $count2, $count3, and $count4 Arguments"
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl12.html 2/2
9/12/2017 Variable scope - global, upvar, and unset
Tcl evaluates variables within a scope delineated by procs, namespaces (see Building
reusable libraries - packages and namespaces), and at the topmost level, the global
scope.
The scope in which a variable will be evaluated can be changed with the global and
upvar commands.
The global command will cause a variable in a local scope (inside a procedure) to
refer to the global variable of that name.
The upvar command is similar. It "ties" the name of a variable in the current scope to
a variable in a different scope. This is commonly used to simulate pass-by-reference
to procs.
You might also encounter the variable command in others' Tcl code. It is part of the
namespace system and is discussed in detail in that chapter.
Normally, Tcl uses a type of "garbage collection" called reference counting in order
to automatically clean up variables when they are not used anymore, such as when
they go "out of scope" at the end of a procedure, so that you don't have to keep
track of them yourself. It is also possible to explicitly unset them with the aptly
named unset command.
The upvar command causes myVar1 to become a reference to otherVar1, and myVar2 to
become a reference to otherVar2, etc. The otherVar variable is declared to be at level
relative to the current procedure. By default level is 1, the next level up.
If a number is used for the level, then level references that many levels up the stack
from the current level.
If the level number is preceded by a # symbol, then it references that many levels
down from the global scope. If level is #0, then the reference is to a variable at the
global level.
If you are using upvar with anything except #0 or 1, you are most likely asking for
trouble, unless you really know what you're doing.
You should avoid using global variables if possible. If you have a lot of globals, you
should reconsider the design of your program.
Note that since there is only one global space it is surprisingly easy to have name
conflicts if you are importing other peoples code and aren't careful. It is
recommended that you start global variables with an identifiable prefix to help avoid
unexpected conflicts.
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl13.html 1/2
9/12/2017 Variable scope - global, upvar, and unset
Example
SetPositive x 5
SetPositive y -5
set x 1
set y 2
for {set i 0} {$i < 5} {incr i} {
set a($i) $i;
}
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl13.html 2/2
9/12/2017 Tcl Data Structures 101 - The list
The list is the basic Tcl data structure. A list is simply an ordered collection of stuff;
numbers, words, strings, or other lists. Even commands in Tcl are just lists in which
the first list entry is the name of a proc, and subsequent members of the list are the
arguments to the proc.
The items in list can be iterated through using the foreach command:
In reality, the above form of foreach is the simple form, but the command is quite
powerful. It will allow you to take more than one variable at a time from the list:
foreach {a b} $listofpairs { ... }. You can even take a variable at a time from multiple
lists! For example: foreach a $listOfA b $listOfB { ... }
Examples
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl14.html 1/2
9/12/2017 Tcl Data Structures 101 - The list
set i 0
foreach j $x {
puts "$j is item number $i in list x"
incr i
}
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl14.html 2/2
9/12/2017 Adding & Deleting members of a list
Lists in Tcl are the right data structure to use when you have an arbitrary number of
things, and you'd like to access them according to their order in the list. In C, you
would use an array. In Tcl, arrays are associated arrays - hash tables, as you'll see
in the coming sections. If you want to have a collection of things, and refer to the
Nth thing (give me the 10th element in this group of numbers), or go through them
in order via foreach.
Take a look at the example code, and pay special attention to the way that sets of
characters are grouped into single list elements.
Example
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl15.html 2/2
9/12/2017 More list commands - lsearch, lsort, lrange
Lists can be searched with the lsearch command, sorted with the lsort command, and
a range of list entries can be extracted with the lrange command.
Example
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl16.html 1/1
9/12/2017 Simple pattern matching - "globbing"
By default, lsearch uses the "globbing" method of finding a match. Globbing is the
wildcarding technique that most Unix shells use.
*
Matches any quantity of any character
?
Matches one occurrence of any character
\X
The backslash escapes a special character in globbing just the way it does in Tcl
substitutions. Using the backslash lets you use glob to match a * or ?.
[...]
Matches one occurrence of any character within the brackets. A range of
characters can be matched by using a range between the brackets. For
example, [a-z] will match any lower case letter.
There is also a glob command that you will see in later sections that uses glob
pattern matching in directories, and returns a list of the matching files.
Example
# Matches
string match f* foo
# Matches
string match f?? foo
# Doesn't match
string match f foo
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl16a.html 1/1
9/14/2017 String Subcommands - length index range
Example
puts "\"[string range $string 5 10]\" are characters between the 5'th and 10'th"
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl17.html 1/1
9/14/2017 String comparisons - compare match first last wordend
There are 6 string subcommands that do pattern and string matching. These are
relatively fast operations, certainly faster than regular expressions, albeit less
powerful.
These comparisons are done alphabetically, not numerically - in other words "a"
is less than "b", and "10" is less than "2".
string first string1 string2
Returns the index of the character in string1 that starts the first match to
string2, or -1 if there is no match.
string last string1 string2
Returns the index of the character in string1 that starts the last match to string2,
or -1 if there is no match.
string wordend string index
Returns the index of the character just after the last one in the word which
contains the index'th character of string. A word is any contiguous set of letters,
numbers or underscore characters, or a single other character.
string wordstart string index
Returns the index of the first character in the word that contains the index'th
character of string. A word is any contiguous set of letters, numbers or
underscore characters, or a single other character.
string match pattern string
Returns 1 if the pattern matches string. The pattern is a glob style pattern.
Example
if {$first != 0} {
puts "$path is a relative path"
} else {
puts "$path is an absolute path"
}
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl18.html 1/2
9/14/2017 String comparisons - compare match first last wordend
# If "/" is not the last character in $path, report the last word.
# else, remove the last "/", and find the next to last "/", and
# report the last word.
incr last
if {$last != [string length $path]} {
set name [string range $path $last end]
puts "The file referenced in $path is $name"
} else {
incr last -2;
set tmp [string range $path 0 $last]
set last [string last "/" $tmp]
incr last;
set name [string range $tmp $last end]
puts "The final directory in $path is $name"
}
# Compare to "a" to determine whether the first char is upper or lower case
set comparison [string compare $name "a"]
if {$comparison >= 0} {
puts "$name starts with a lowercase letter\n"
} else {
puts "$name starts with an uppercase letter\n"
}
}
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl18.html 2/2
9/14/2017 Modifying Strings - tolower, toupper, trim, format
These are the commands which modify a string. Note that none of these modify the
string in place. In all cases a new string is returned.
Example
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl19.html 2/2
9/14/2017 Regular Expressions 101
Tcl also supports string operations known as regular expressions Several commands
can access these methods with a -regexp argument, see the man pages for which
commands support regular expressions.
There are also two explicit commands for parsing regular expressions.
^
Matches the beginning of a string
$
Matches the end of a string
.
Matches any single character
*
Matches any count (0-n) of the previous character
+
Matches any count, but at least 1 of the previous character
[...]
Matches any character of a set of characters
[^...]
Matches any character *NOT* a member of the set of characters following the
^.
(...)
Groups a set of characters into a subSpec.
Regular expressions are similar to the globbing that was discussed in lessons 16 and
18. The main difference is in the way that sets of matched characters are handled.
In globbing the only way to select sets of unknown text is the * symbol. This
matches to any quantity of any character.
In regular expression parsing, the * symbol matches zero or more occurrences of the
character immediately proceeding the *. For example a* would match a, aaaaa, or a
blank string. If the character directly before the * is a set of characters within square
brackets, then the * will match any quantity of all of these characters. For example,
[a-c]* would match aa, abc, aabcabc, or again, an empty string.
The + symbol behaves roughly the same as the *, except that it requires at least one
character to match. For example, [a-c]+ would match a, abc, or aabcabc, but not an
empty string.
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl20.html 1/2
9/14/2017 Regular Expressions 101
Regular expression parsing is more powerful than globbing. With globbing you can
use square brackets to enclose a set of characters any of which will be a match.
Regular expression parsing also includes a method of selecting any character not in
a set. If the first character after the [ is a caret (^), then the regular expression
parser will match any character not in the set of characters between the square
brackets. A caret can be included in the set of characters to match (or not) by
placing it in any position other than the first.
The regexp command is similar to the string match command in that it matches an exp
against a string. It is different in that it can match a portion of a string, instead of
the entire string, and will place the characters matched into the matchVar variable.
Regsubwill copy the contents of the string to a new variable, substituting the
characters that match exp with the characters in subSpec. If subSpec contains a & or \0,
then those characters will be replaced by the characters that matched exp. If the
number following a backslash is 1-9, then that backslash sequence will be replaced
by the appropriate portion of exp that is enclosed within parentheses.
Note that the exp argument to regexp or regsub is processed by the Tcl substitution
pass. Therefore quite often the expression is enclosed in braces to prevent any
special processing by Tcl.
Example
#
# Match the first substring with lowercase letters only
#
set result [regexp {[a-z]+} $sample match]
puts "Result: $result match: $match"
#
# Match the first two words, the first one allows uppercase
set result [regexp {([A-Za-z]+) +([a-z]+)} $sample match sub1 sub2 ]
puts "Result: $result Match: $match 1: $sub1 2: $sub2"
#
# Replace a word
#
regsub "way" $sample "lawsuit" sample2
puts "New: $sample2"
#
# Use the -all option to count the number of "words"
#
puts "Number of words: [regexp -all {[^ ]+} $sample]"
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl20.html 2/2
9/14/2017 More Examples Of Regular Expressions
Regular expressions provide a very powerful method of defining a pattern, but they
are a bit awkward to understand and to use properly. So let us examine some more
examples in detail.
How do we design our regular expression for this problem? By examining typical
examples of the strings we want to match:
Invalid numbers (that is, strings we do not want to recognise as numbers but
superficially look like them):
-, +., 0.0.1, 0..2, ++1
We will accept them - because they normally are accepted and because
excluding them makes our pattern more complicated.
A number can start with a sign (- or +) or with a digit. This can be captured
with the expression [-+]?, which matches a single "-", a single "+" or nothing.
A number can have zero or more digits in front of a single period (.) and it can
have zero or more digits following the period. Perhaps: [0-9]*\.[0-9]* will do ...
A number may not contain a period at all. So, revise the previous expression
to: [0-9]*\.?[0-9]*
1. Try the expression with a bunch of examples like the ones above and see if the
proper ones match and the others do not.
2. Try to make it look nicer, before we start off testing it. For instance the class of
characters "[0-9]" is so common that it has a shortcut, "\d". So, we could settle
for:
[-+]?\d*\.?\d*
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl20a.html 1/5
9/14/2017 More Examples Of Regular Expressions
instead. Or we could decide that we want to capture the digits before and after
the period for special processing:
[-+]?([0-9])*\.?([0-9]*)
3. Or, and that may be a good strategy in general!, we can carefully examine the
pattern before we start actually using it.
You see, there is a problem with the above pattern: all the parts are optional, that
is, each part can match a null string - no sign, no digits before the period, no period,
no digits after the period. In other words: Our pattern can match an empty string!
The character before a minus or a plus, if there is any, can not be another digit,
a period or a minus or plus. Let us make it a space or a tab or the beginning of
the string: ^|[ \t]
Any sequence of digits before the period (if there is one) is allowed: [0-9]+\.?
There may be zero digits in front of the period, but then there must be at least
one digit behind it: \.[0-9]+
The character after the string (if any) can not be a "+","-" or "." as that would
get us into the unacceptable number-like strings: $|[^+-.] (The dollar sign
signifies the end of the string)
Before trying to write down the complete regular expression, let us see what
different forms we have:
No period: [-+]?[0-9]+
(^|[ \t])([-+]?([0-9]+|\.[0-9]+|[0-9]+\.[0-9]*))($|[^+-.])
Or:
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl20a.html 2/5
9/14/2017 More Examples Of Regular Expressions
(^|[ \t])([-+]?(\d+|\.\d+|\d+\.\d*))($|[^+-.])
The parentheses are needed to distinguish the alternatives introduced by the vertical
bar and to capture the substring we want to have. Each set of parentheses also
defines a substring and this can be put into a separate variable:
regexp {.....} $line whole char_before number nosign char_after
#
# Or simply only the recognised number (x's as placeholders, the
# last can be left out
#
regexp {.....} $line x x number
Tip: To identify these substrings: just count the opening parentheses from left to
right.
Suppose we do not know the enclosing character (it can be " or '). Then:
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl20a.html 3/5
9/14/2017 More Examples Of Regular Expressions
You can use this technique to see if a word occurs twice in the same line of
text:
(The pattern \y matches the beginning or the end of a word and \w+ indicates
we want at least one character).
#
# Use the return value of [regexp] to count the number of
# parentheses ...
#
if { [regexp -all {(} $string] != [regexp -all {)} $string] } {
puts "Parentheses unbalanced!"
}
Of course, this is just a rough check. A better one is to see if at any point while
scanning the string there are more close parentheses than open parentheses.
We can easily extract the parentheses and put them in a list (the -inline option
does that):
foreach p $parens {
incr balance $change($p)
if { $balance < 0 } {
puts "Parentheses unbalanced!"
}
}
if { $balance != 0 } {
puts "Parentheses unbalanced!"
}
Finally: Regular expressions are very powerful, but they have certain theoretical
limitations. One of these limitations is that they are not suitable for parsing
arbitrarily nested text.
You can experiment with regular expressions using the VisualRegexp or Visual
REGEXP applications.
More on the theoretical background and practical use of regular expressions (there is
lots to cover!) can be found in the book Mastering Regular Expressions by J. Friedl.
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl20a.html 4/5
9/14/2017 More Examples Of Regular Expressions
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl20a.html 5/5
9/14/2017 More Quoting Hell - Regular Expressions 102
The regular expression (exp) in the two regular expression parsing commands is
evaluated by the Tcl parser during the Tcl substitution phase. This can provide a
great deal of power, and also requires a great deal of care.
These examples show some of the trickier aspects of regular expression evaluation.
The fields in each example are discussed in painful detail in the most verbose level.
A left square bracket ([) has meaning to the substitution phase, and to the
regular expression parser.
A set of parentheses, a plus sign, and a star have meaning to the regular
expression parser, but not the Tcl substitution phase.
A backslash sequence (\n, \t, etc) has meaning to the Tcl substitution phase,
but not to the regular expression parser.
A backslash escaped character (\[) has no special meaning to either the Tcl
substitution phase or the regular expression parser.
The phase at which a character has meaning affects how many escapes are
necessary to match the character you wish to match. An escape can be either
enclosing the phrase in braces, or placing a backslash before the escaped character.
Note: You can copy the code and run it in tclsh or wish to see the effects.
Example
#
# Examine an overview of UNIX/Linux disks
#
set list1 [list \
{/dev/wd0a 17086 10958 5272 68% /}\
{/dev/wd0f 179824 127798 48428 73% /news}\
{/dev/wd0h 1249244 967818 218962 82% /usr}\
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl21.html 1/2
9/14/2017 More Quoting Hell - Regular Expressions 102
#
# Extracting a hexadecimal value ...
#
set line {Interrupt Vector? [32(0x20)]}
regexp "\[^\t]+\t\\\[\[0-9]+\\(0x(\[0-9a-fA-F]+)\\)]" $line match hexval
puts "Hex Default is: 0x$hexval"
#
# Matching the special characters as if they were ordinary
#
set str2 "abc^def"
regexp "\[^a-f]*def" $str2 match
puts "using \[^a-f] the match is: $match"
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl21.html 2/2
9/14/2017 Associative Arrays
Associative Arrays.
Languages like C, BASIC, FORTRAN and Java support arrays in which the index value
is an integer. Tcl, like most scripting languages (Perl, Python, PHP, etc...) supports
associative arrays (also known as "hash tables") in which the index value is a string.
The syntax for an associative array is to put the index within parentheses:
There are several array commands aside from simply accessing and creating arrays
which will be discussed in this and the next lesson.
When an associative array name is given as the argument to the global command, all
the elements of the associative array become available to that proc. For this reason,
Brent Welch recommends (in Practical Programming in Tcl and Tk) using an
associative array for the state structure in a package.
This method makes it simpler to share data between many procs that are working
together, and doesn't pollute the global namespace as badly as using separate
globals for all shared data items.
Another common use for arrays is to store tables of data. In the example below we
use an array to store a simple database of names.
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl22.html 1/3
9/14/2017 Associative Arrays
Example
# Create a new ID (stored in the name array too for easy access)
incr name(ID)
set id $name(ID)
#
# Initialise the array and add a few names
#
global name
set name(ID) 0
#
# Check the contents of our database
# The parray command is a quick way to
# print it
#
parray name
#
# Some array commands
#
array set array1 [list {123} {Abigail Aardvark} \
{234} {Bob Baboon} \
{345} {Cathy Coyote} \
{456} {Daniel Dog} ]
puts "Array1 has the following entries: \n [array names array1] \n"
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl22.html 2/3
9/14/2017 Associative Arrays
# Create an array
for {set i 0} {$i < 5} {incr i} { set a($i) test }
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl22.html 3/3
9/14/2017 More On Arrays - Iterating and use in procedures
Often you will want to loop through the contents of an associative array - without
having to specify the elements explicitly. For this the array names and array get
commands are very useful. With both you can give a (glob-style) pattern to select
what elements you need:
#
# Get names and values directly
#
foreach {name value} [array get mydata] {
puts "Data on \"$name\": $value"
}
Note, however, that the elements will not be returned in any predictable order: this
has to do with the underlying "hash table". If you want a particular ordering
(alphabetical for instance), use code like:
foreach name [lsort [array names mydata]] {
puts "Data on \"$name\": $mydata($name)"
}
While arrays are great as a storage facility for some purposes, they are a bit tricky
when you pass them to a procedure: they are actually collections of variables. This
will not work:
proc print12 {a} {
puts "$a(1), $a(2)"
}
print12 $array
The reason is very simple: an array does not have a value. Instead the above code
should be:
proc print12 {array} {
upvar $array a
puts "$a(1), $a(2)"
}
print12 array
So, instead of passing a "value" for the array, you pass the name. This gets aliased
(via the upvar command) to a local variable (that behaves the as original array). You
can make changes to the original array in this way too.
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl23.html 1/3
9/14/2017 More On Arrays - Iterating and use in procedures
Example
#
# The example of the previous lesson revisited - to get a
# more general "database"
#
# Create a new ID (stored in the name array too for easy access)
incr name(ID)
set id $name(ID)
# Loop over the last names: make a map from last name to ID
#
# Store in a temporary array:
# an "inverse" map of last name to ID)
#
set last $name($n)
set tmp($last) $id
}
#
# Now we can easily print the names in the order we want!
#
foreach last [lsort [array names tmp]] {
set id $tmp($last)
puts " $name($id,first) $name($id,last)"
}
}
#
# Initialise the array and add a few names
#
set fictional_name(ID) 0
set historical_name(ID) 0
#
# Some simple reporting
#
puts "Fictional characters:"
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl23.html 2/3
9/14/2017 More On Arrays - Iterating and use in procedures
report fictional_name
puts "Historical characters:"
report historical_name
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl23.html 3/3
9/14/2017 Dictionaries
Tcl arrays are collections of variables, rather than values. This has advantages in
some situations (e.g., you can use variable traces on them), but also has a number
of drawbacks:
The comma used here is not a special piece of syntax, but instead just part of
the string key. In other words, we are using a one-dimensional array, with keys
like "foo,2" and "bar,3". This is quite possible, but it can become very clumsy
(there can be no intervening spaces for instance).
Arrays cannot be included in other data structures, such as lists, or sent over a
communications channel, without first packing and unpacking them into a string
value.
In Tcl 8.5 the dict command has been introduced. This provides efficient access to
key-value pairs, just like arrays, but dictionaries are pure values. This means that
you can pass them to a procedure just as a list or a string, without the need for dict.
Tcl dictionaries are therefore much more like Tcl lists, except that they represent a
mapping from keys to values, rather than an ordered sequence.
Unlike arrays, you can nest dictionaries, so that the value for a particular key
consists of another dictionary. That way you can elegantly build complicated data
structures, such as hierarchical databases. You can also combine dictionaries with
other Tcl data structures. For instance, you can build a list of dictionaries that
themselves contain lists.
#
# Create a dictionary:
# Two clients, known by their client number,
# with forenames, surname
#
dict set clients 1 forenames Joe
dict set clients 1 surname Schmoe
dict set clients 2 forenames Anne
dict set clients 2 surname Other
#
# Print a table
#
puts "Number of clients: [dict size $clients]"
dict for {id info} $clients {
puts "Client $id:"
dict with info {
puts " Name: $forenames $surname"
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl23a.html 1/4
9/14/2017 Dictionaries
}
}
We fill a dictionary, called clients, with the information we have on two clients.
The dictionary has two keys, "1" and "2" and the value for each of these keys is
itself a (nested) dictionary — again with two keys: "forenames" and "surname".
The dict set command accepts a list of key names which act as a path through
the dictionary. The last argument to the command is the value that we want to
set. You can supply as many key arguments to the dict set command as you
want, leading to arbitrarily complicated nested data structures. Be careful
though! Flat data structure designs are usually better than nested for most
problems.
The dict for command then loops through each key and value pair in the
dictionary (at the outer-most level only). dict for is essentially a version of
foreach that is specialised for dictionaries. We could also have written this line
as:
foreach {id info} $clients { ... }
This takes advantage of the fact that, in Tcl, every dictionary is also a valid Tcl
list, consisting of a sequence of name and value pairs representing the contents
of the dictionary. The dict for command is preferred when working with
dictionaries, however, as it is both more efficient, and makes it clear to readers
of the code that we are dealing with a dictionary and not just a list.
To get at the actual values in the dictionary that is stored with the client IDs we
use the dict with command. This command takes the dictionary and unpacks it
into a set of local variables in the current scope. For instance, in our example,
the "info" variable on each iteration of the outer loop will contain a dictionary
with two keys: "forenames" and "surname". The dict with command unpacks
these keys into local variables with the same name as the key and with the
associated value from the dictionary. This allows us to use a more convenient
syntax when accessing the values, instead of having to use dict get everywhere.
A related command is the dict update command, that allows you to specify
exactly which keys you want to convert into variables. Be aware that any
changes you make to these variables will be copied back into the dictionary
when the dict with command finishes.
The order in which elements of a dictionary are returned during a dict for loop is
defined to be the chronological order in which keys were added to the dictionary. If
you need to access the keys in some other order, then it is advisable to explicitly
sort the keys first. For example, to retrieve all elements of a dictionary in
alphabetical order, based on the key, we can use the lsort command:
Example
In this example, we convert the simple database of the previous lessons to work
with dictionaries instead of arrays.
#
# The example of the previous lesson revisited - using dicts.
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl23a.html 2/4
9/14/2017 Dictionaries
#
# Create a new ID (stored in the name array too for easy access)
dict incr db ID
set id [dict get $db ID]
# Loop over the last names: make a map from last name to ID
#
# Now we can easily print the names in the order we want!
#
foreach last [lsort [dict keys $tmp]] {
set id [dict get $tmp $last]
puts " [dict get $db $id first] $last"
}
}
#
# Initialise the array and add a few names
#
dict set fictional_name ID 0
dict set historical_name ID 0
#
# Some simple reporting
#
puts "Fictional characters:"
report $fictional_name
puts "Historical characters:"
report $historical_name
Note that in this example we use dictionaries in two different ways. In the addname
procedure, we pass the dictionary variable by name and use upvar to make a link to
it, as we did previously for arrays. We do this so that changes to the database are
reflected in the calling scope, without having to return a new dictionary value. (Try
changing the code to avoid using upvar). In the report procedure, however, we pass
the dictionary as a value and use it directly. Compare the dictionary and array
versions of this example (from the previous lesson) to see the differences between
the two data structures and how they are used.
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl23a.html 3/4
9/14/2017 Dictionaries
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl23a.html 4/4
9/14/2017 File Access 101
Tcl provides several methods to read from and write to files on disk. The simplest
methods to access a file are via gets and puts. When there is a lot of data to be read,
however, it is sometimes more efficient to use the read command to load an entire
file, and then parse the file into lines with the split command.
These methods can also be used for communicating over sockets and pipes. It is
even possible, via the so-called virtual file system to use files stored in memory
rather than on disk. Tcl provides an almost uniform interface to these very different
resources, so that in general you do not need to concern yourself with the details.
close fileID
Closes a file previously opened with open, and flushes any remaining output.
gets fileID ?varName?
Reads a line of input from FileID, and discards the terminating newline.
If there is a varName argument, gets returns the number of characters read (or -1
if an EOF occurs), and places the line of input in varName.
If varName is not specified, gets returns the line of input. An empty string will be
returned if:
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl24.html 1/3
9/14/2017 File Access 101
tell fileID
Returns the position of the access pointer in fileID as a decimal string.
flush fileID
Flushes any output that has been buffered for fileID.
eof fileID
returns 1 if an End Of File condition exists, otherwise returns 0.
The file I/O is buffered. The output may not be sent out when you expect it to
be sent. Files will all be closed and flushed when your program exits normally,
but may only be closed (not flushed) if the program is terminated in an
unexpected manner.
There are a finite number of open file slots available. If you expect the program
to run in a manner that will cause it to open several files, remember to close
the files when you are done with them.
An empty line is indistinguishable from an EOF with the command:
Use the eof command to determine if the file is at the end or use the other form
of gets (see the example).
You can't overwrite any data in a file that was opened with a (append) access.
You can, however seek to the beginning of the file for gets commands.
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl24.html 2/3
9/14/2017 File Access 101
Opening a file with the w+ access will allow you to overwrite data, but will delete
all existing data in the file.
Opening a file with the r+ access will allow you to overwrite data, while saving
the existing data in the file.
By default the commands assume that strings represent "readable" text. If you
want to read "binary" data, you will have to use the fconfigure command.
Often, especially if you deal with configuration data for your programs, you can
use the source command instead of the relatively low-level commands presented
here. Just make sure your data can be interpreted as Tcl commands and
"source" the file.
Example
#
# Count the number of lines in a text file
#
set infile [open "myfile.txt" r]
set number 0
#
# gets with two arguments returns the length of the line,
# -1 if the end of the file is found
#
while { [gets $infile line] >= 0 } {
incr number
}
close $infile
#
# Also report it in an external file
#
set outfile [open "report.out" w]
puts $outfile "Number of lines: $number"
close $outfile
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl24.html 3/3
9/14/2017 Information about Files - file, glob
There are two commands that provide information about the file system, glob and
file.
globprovides the access to the names of files in a directory. It uses a name matching
mechanism similar to the UNIX ls command or the Windows (DOS) dir command, to
return a list of names that match a pattern.
Between these two commands, a program can obtain most of the information that it
may need and manipulate the files and directories.
While retrieving information about what files are present and what properties they
have is usually a highly platform-dependent matter, Tcl provides an interface that
hides almost all details that are specific to the platform (but are irrelevant to the
programmer).
To take advantage of this feature, always manipulate file names via the file join, file
split commands and the others in the first category.
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl25.html 1/5
9/14/2017 Information about Files - file, glob
Because external commands may not always deal gracefully with the uniform
representation that Tcl employs (with forward slashes as directory separators), Tcl
also provides a command to turn the string into one that is native to the platform:
#
# On Windows the name becomes "..\myfile.out"
#
set newname [file nativename [file join ".." "myfile.out"]]
Retrieving all the files with extension ".tcl" in the current directory:
(The clock command turns the number of seconds returned by the file mtime
command into a simple date string, like "12/22/04")
switches may be one of the following (there are more switches available):
-nocomplain
Allows glob to return an empty list without causing an error. Without this
flag, an error would be generated when the empty list was returned.
-types typeList
Selects which type of files/directory the command should return. The
typeList may consist of type letters, like a "d" for directories and "f" for
ordinary files as well as letters and keywords indicating the user's
permissions ("r" for files/directories that can be read for instance).
--
Marks the end of switches. This allows the use of "-" in a pattern without
confusing the glob parser.
patternfollows the same matching rules as the string match globbing rules with
these exceptions:
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl25.html 2/5
9/14/2017 Information about Files - file, glob
Note that the filenames that match pattern are returned in an arbitrary order
(that is, do not expect them to be sorted in alphabetical order, for instance).
Because this calls lstat, if name is a symbolic link, the values in varName will refer
to the link, not the file that is linked to. (See also the stat subcommand)
file mkdir name
Create a new directory name.
file mtime name
Returns the time of the last modification in seconds since Jan 1, 1970 or
whatever start date the system uses.
file owned name
Returns 1 if the file is owned by the current user, otherwise returns 0.
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl25.html 3/5
9/14/2017 Information about Files - file, glob
file...................................Normal file
directory........................Directory
characterSpecial.......Character oriented device
blockSpecial.............. Block oriented device
fifo...................................Named pipe
link..................................Symbolic link
socket...........................Named socket
Note: The overview given above does not cover all the details of the various
subcommands, nor does it list all subcommands. Please check the man pages for
these.
Example
#
# Report all the files and subdirectories in the current directory
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl25.html 4/5
9/14/2017 Information about Files - file, glob
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl25.html 5/5
9/14/2017 Running other programs from Tcl - exec, open
So far the lessons have dealt with programming within the Tcl interpreter. However,
Tcl is also useful as a scripting language to tie other packages or programs together.
To accomplish this function, Tcl has two ways to start another program:
open ...... run a new program with I/O connected to a file descriptor
exec ...... run a new program as a subprocess
The open call is the same call that is used to open a file. If the first character in the
file name argument is a "pipe" symbol (|), then open will treat the rest of the
argument as a program name, and will run that program with the standard input or
output connected to a file descriptor. This "pipe" connection can be used to read the
output from that other program or to write fresh input data to it or both.
If the "pipe" is opened for both reading and writing you must be aware that the
pipes are buffered. The output from a puts command will be saved in an I/O buffer
until the buffer is full, or until you execute a flush command to force it to be
transmitted to the other program. The output of this other program will not be
available to a read or gets until its output buffer is filled up or flushed explicitly.
(Note: as this is internal to this other program, there is no way that your Tcl script
can influence that. The other program simply must cooperate. Well, that is not
entirely true: the expect extension actually works around this limitation by exploiting
deep system features.)
The exec call is similar to invoking a program (or a set of programs piped together)
from the prompt in an interactive shell or a DOS-box or in a UNIX/Linux shell script.
It supports several styles of output redirection, or it can return the output of the
other program(s) as the return value of the exec call.
switches are:
-keepnewline
Retains a trailing newline in the pipeline's output. Normally a trailing
newline will be deleted.
--
Marks the end of the switches. The next string will be treated as arg1, even
if it starts with a "-"
will start the program myprog in the background, and return immediately.
There is no connection between that program and the Tcl script, both can
run on independently.
The & must be the last argument - you can use all other types of
arguments in front of it.
There are many I/O redirection commands. The main subset of these
commands is:
|
Pipes the standard output of the command preceding the pipe symbol into
the standard input of the command following the pipe symbol.
< fileName
The first program in the pipe will read input from fileName.
<@ fileID
The first program in the pipe will read input from the Tcl descriptor fileID.
fileID is the value returned from an open ... "r" command.
<< value
The first program in the pipe will read value as its input.
> fileName
The output of the last program in the pipe will be sent to fileName. Any
previous contents of fileName will be lost.
>> fileName
The output of the last program in the pipe will be appended to fileName.
2> fileName
The standard error from all the programs in the pipe will be sent to
fileName. Any previous contents of fileName will be lost.
2>> fileName
The standard error from all the programs in the pipe will be appended to
fileName.
>@ fileID
The output from the last program in the pipe will be written to fileID. fileID
is the value returned from an open ... "w" command.
If you are familiar with shell programming, there are a few differences to be aware
of when you are writing Tcl scripts that use the exec and open calls.
You don't need the quotes that you would put around arguments to escape
them from the shell expanding them. In the example, the argument to the sed
command is not put in quotes. If it were put in quotes, the quotes would be
passed to sed, instead of being stripped off (as the shell does), and sed would
report an error.
If you use the open |cmd "r+" construct, you must follow each puts with a flush to
force Tcl to send the command from its buffer to the program. The output from
the program itself may be buffered in its output buffer.
You can sometimes force the output from the external program to flush by
sending an exit command to the process.
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl26.html 2/4
9/14/2017 Running other programs from Tcl - exec, open
You can also use the fconfigure command to make a connection (channel)
unbuffered.
If one of the commands in an open |cmd fails the open does not return an error.
However, attempting to read input from the file descriptor with gets $file will
return an empty string. Using the gets $file input construct will return a
character count of -1.
Tcl does not expand file names like the UNIX/Linux shells do. So:
exec ls *.tcl
will fail - there is most probably no file with the literal name "*.tcl".
If you need such an expansion, you should use the glob command:
where the {*} prefix is used to force the list to become individual arguments.
If one of the commands in an exec call fails to execute, the exec will return an
error, and the error output will include the last line describing the error.
The exec treats any output to standard error to be an indication that the
external program failed. This is simply a conservative assumption: many
programs behave that way and they are sloppy in setting return codes.
To inspect the return code from a program and the possible reason for failure,
you can use the global errorInfo variable:
Example
#
# Write a Tcl script to get a platform-independent program:
#
# Create a unique (mostly) file name for a Tcl program
set TMPDIR "/tmp"
if { [info exists ::env(TMP)] } {
set TMPDIR $::env(TMP)
}
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl26.html 3/4
9/14/2017 Running other programs from Tcl - exec, open
}
set tempFileName "$TMPDIR/invert_[pid].tcl"
puts $outfl {
set len [gets stdin line]
if {$len < 5} {exit -1}
#
# Run the new Tcl script:
#
# Open a pipe to the program (for both reading and writing: r+)
#
set io [open "|[info nameofexecutable] $tempFileName" r+]
#
# send a string to the new program
# *MUST FLUSH*
puts $io "This will come back backwards."
flush $io
# Clean up
file delete $tempFileName
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl26.html 4/4
9/14/2017 Learning the existence of commands and variables ? - info
Tcl provides a number of commands for introspection - commands that tell what is
going on in your program, what the implementation is of your procedures, which
variables have been set and so on.
The info command allows a Tcl program to obtain information from the Tcl
interpreter. The next three lessons cover aspects of the info command. (Other
commands allowing introspection involve: traces, namespaces, commands scheduled
for later execution via the after command and so on.)
This lesson covers the info subcommands that return information about which procs,
variables, or commands are currently in existence in this instance of the interpreter.
By using these subcommands you can determine if a variable or proc exists before
you try to access it.
The code below shows how to use the info exists command to make an incr that will
never return a no such variable error, since it checks to be certain that the variable
exists before incrementing it:
Almost all these commands take a pattern that follow the string match rules. If pattern
is not provided, a list of all items is returned (as if the pattern was "*").
Example
set a 100
safeIncr a
puts "After calling SafeIncr with a variable with a value of 100: $a"
safeIncr b -3
puts "After calling safeIncr with a non existent variable by -3: $b"
set b 100
safeIncr b -3
puts "After calling safeIncr with a variable whose value is 100 by -3: $b"
proc localproc {} {
global argv
set loc1 1
set loc2 2
puts "\nLocal variables accessible in this proc are: [lsort [info locals]]"
puts "\nVariables accessible from this proc are: [lsort [info vars]]"
puts "\nGlobal variables visible from this proc are: [lsort [info globals]]"
}
localproc
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl27.html 2/2
9/14/2017 State of the interpreter - info
There are a number of subcommands to the info command that provide information
about the current state of the interpreter. These commands provide access to
information like the current version and patchlevel, what script is currently being
executed, how many commands have been executed, or how far down in the call
tree the current proc is executing.
The info tclversion and info patchlevel can be used to find out if the revision level of
the interpreter running your code has the support for features you are using. If you
know that certain features are not available in certain revisions of the interpreter,
you can define your own procs to handle this, or just exit the program with an error
message.
The info cmdcount and info level can be used while optimizing a Tcl script to find out
how many levels and commands were necessary to accomplish a function.
Note that the pid command is not part of the info command, but a command in its
own right.
(Note: There are several other subcommands that can be useful at times)
info cmdcount
Returns the total number of commands that have been executed by this
interpreter.
info level ?number?
Returns the stack level at which the compiler is currently evaluating code. 0 is
the top level, 1 is a proc called from top, 2 is a proc called from a proc, etc.
If number is a positive value, info level returns a the name and arguments of the
proc at that level on the stack. Number is that same value that info level would
return if it were called in the proc being referenced.
If number number is a negative value, it refers to the current level plus number.
Thus, info level returns a the name and arguments of the proc at that level on
the stack.
info patchlevel
Returns the value of the global variable tcl_patchlevel. This is a three-levels
version number identifying the Tcl version, like: "8.4.6"
info script
Returns the name of the file currently being evaluated, if one is being
evaluated. If there is no file being evaluated, returns an empty string.
This can be used for instance to determine the directory holding other scripts or
files of interest (they often live in the same directory or in a related directory),
without having to hardcode the paths.
info tclversion
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl28.html 1/2
9/14/2017 State of the interpreter - info
Returns the value of the global variable tcl_version. This is the revision number
of this interpreter, like: "8.4".
pid
Returns the process id of the current process.
Example
puts "This is how many commands have been executed: [info cmdcount]"
puts "Now *THIS* many commands have been executed: [info cmdcount]"
#
# Use [info script] to determine where the other files of interest
# reside
#
set sysdir [file dirname [info script]]
source [file join $sysdir "utils.tcl"]
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl28.html 2/2
9/14/2017 Information about procs - info
The info command includes a set of subcommands that will provide all the info you
could want about a proc. These subcommands will return the body of a proc, the
arguments to the proc, and the value of any default arguments.
Example
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl29.html 1/1
9/14/2017 Modularization - source
Modularization - source
The source command will load a file and execute it. This allows a program to be
broken up into multiple files, with each file defining procedures and variables for a
particular area of functionality. For instance, you might have a file called database.tcl
that contains all the procedures for dealing with a database, or a file called gui.tcl
that handles creating a graphical user interface with Tk. The main script can then
simply include each file using the source command. More powerful techniques for
program modularization are discussed in the next lesson on packages.
source fileName
Reads the script in fileName and executes it. If the script executes successfully,
source returns the value of the last statement in the script.
If there is an error in the script, source will return that error.
If there is a return (other than within a proc definition) then source will return
immediately, without executing the remainder of the script.
If fileName starts with a tilde (~) then $env(HOME) will substituted for the tilde, as is
done in the file command.
Example
sourcedata.tcl:
sourcemain.tcl:
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl30.html 1/2
9/14/2017 Modularization - source
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl30.html 2/2
9/14/2017 Building reusable libraries - packages and namespaces
The previous lesson showed how the source command can be used to separate a
program into multiple files, each responsible for a different area of functionality. This
is a simple and useful technique for achieving modularity. However, there are a
number of drawbacks to using the source command directly. Tcl provides a more
powerful mechanism for handling reusable units of code called packages. A package
is simply a bundle of files implementing some functionality, along with a name that
identifies the package, and a version number that allows multiple versions of the
same package to be present. A package can be a collection of Tcl scripts, or a binary
library, or a combination of both. Binary libraries are not discussed in this tutorial.
Using packages
The package command provides the ability to use a package, compare package
versions, and to register your own packages with an interpreter. A package is loaded
by using the package require command and providing the package name and optionally a
version number. The first time a script requires a package Tcl builds up a database of
available packages and versions. It does this by searching for package index files in
all of the directories listed in the tcl_pkgPath and auto_path global variables, as well as
any subdirectories of those directories. Each package provides a file called
pkgIndex.tcl that tells Tcl the names and versions of any packages in that directory,
and how to load them if they are needed.
It is good style to start every script you create with a set of package require
statements to load any packages required. This serves two purposes: making sure
that any missing requirements are identified as soon as possible; and, clearly
documenting the dependencies that your code has. Tcl and Tk are both made
available as packages and it is a good idea to explicitly require them in your scripts
even if they are already loaded as this makes your scripts more portable and
documents the version requirements of your script.
Creating a package
The first step is to add a package provide statement to your script. It is good style to
place this statement at the top of your script. The package provide command tells Tcl
the name of your package and the version being provided.
The next step is to create a pkgIndex.tcl file. This file tells Tcl how to load your
package. In essence the index file is simply a Tcl file which is loaded into the
interpreter when Tcl searches for packages. It should use the package ifneeded
command register a script which will load the package when it is required. The
pkgIndex.tcl file is evaluated globally in the interpreter when Tcl first searches for any
package. For this reason it is very bad style for an index script to do anything other
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl31.html 1/5
9/14/2017 Building reusable libraries - packages and namespaces
than tell Tcl how to load a package; index scripts should not define procs, require
packages, or perform any other action which may affect the state of the interpreter.
The simplest way to create a pkgIndex.tcl script is to use the pkg_mkIndex command.
The pkg_mkIndex command scans files which match a given pattern in a directory looking
for package provide commands. From this information it generates an appropriate
pkgIndex.tcl file in the directory.
Once a package index has been created, the next step is to move the package to
somewhere that Tcl can find it. The tcl_pkgPath and auto_path global variables contain a
list of directories that Tcl searches for packages. The package index and all the files
that implement the package should be installed into a subdirectory of one of these
directories. Alternatively, the auto_path variable can be extended at run-time to tell
Tcl of new places to look for packages.
Namespaces
One problem that can occur when using packages, and particularly when using code
written by others is that of name collision. This happens when two pieces of code try
to define a procedure or variable with the same name. In Tcl when this occurs the
old procedure or variable is simply overwritten. This is sometimes a useful feature,
but more often it is the cause of bugs if the two definitions are not compatible. To
solve this problem, Tcl provides a namespace command to allow commands and
variables to be partitioned into separate areas, called namespaces. Each namespace
can contain commands and variables which are local to that namespace and cannot
be overwritten by commands or variables in other namespaces. When a command in
a namespace is invoked it can see all the other commands and variables in its
namespace, as well as those in the global namespace. Namespaces can also contain
other namespaces. This allows a hierarchy of namespaces to be created in a similar
way to a file system hierarchy, or the Tk widget hierarchy. Each namespace itself
has a name which is visible in its parent namespace. Items in a namespace can be
accessed by creating a path to the item. This is done by joining the names of the
items with ::. For instance, to access the variable bar in the namespace foo, you
could use the path foo::bar. This kind of path is called a relative path because Tcl will
try to follow the path relative to the current namespace. If that fails, and the path
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl31.html 2/5
9/14/2017 Building reusable libraries - packages and namespaces
represents a command, then Tcl will also look relative to the global namespace. You
can make a path fully-qualified by describing its exact position in the hierachy from
the global namespace, which is named ::. For instance, if our foo namespace was a
child of the global namespace, then the fully-qualified name of bar would be
::foo::bar. It is usually a good idea to use fully-qualified names when referring to any
item outside of the current namespace to avoid surprises.
A namespace can export some or all of the command names it contains. These
commands can then be imported into another namespace. This in effect creates a
local command in the new namespace which when invoked calls the original
command in the original namespace. This is a useful technique for creating short-
cuts to frequently used commands from other namespaces. In general, a namespace
should be careful about exporting commands with the same name as any built-in Tcl
command or with a commonly used name.
Some of the most important commands to use when dealing with namespaces are:
Example
This example creates a package which provides a stack data structure.
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl31.html 3/5
9/14/2017 Building reusable libraries - packages and namespaces
# Set up state
variable stack
variable id 0
}
# Destroy a stack
proc ::tutstack::destroy {token} {
variable stack
unset stack($token)
}
if {[empty $token]} {
error "stack empty"
}
tutstack::destroy $stack
Ensembles
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl31.html 5/5
9/14/2017 Creating Commands - eval
One difference between Tcl and most other compilers is that Tcl will allow an
executing program to create new commands and execute them while running.
A tcl command is defined as a list of strings in which the first string is a command or
proc. Any string or list which meets this criteria can be evaluated and executed.
The eval command will evaluate a list of strings as though they were commands
typed at the % prompt or sourced from a file. The eval command normally returns
the final value of the commands being evaluated. If the commands being evaluated
throw an error (for example, if there is a syntax error in one of the strings), then
eval will will throw an error.
Note that either concat or list may be used to create the command string, but that
these two commands will create slightly different command strings.
Example
#
# Define a proc using lists
#
eval $cmd
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl32.html 1/2
9/14/2017 Creating Commands - eval
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl32.html 2/2
9/14/2017 More command construction - format, list
There may be some unexpected results when you try to compose command strings
for eval.
For instance
eval puts OK
The reason that the second command generates an error is that the eval uses
concat to merge its arguments into a command string. This causes the two words
Not OK to be treated as two arguments to puts. If there is more than one
argument to puts, the first argument must be a file pointer.
As long as you keep track of how the arguments you present to eval will be
grouped, you can use many methods of creating the strings for eval, including the
string commands and format.
The recommended methods of constructing commands for eval is to use the list and
lappend commands. These commands become difficult to use, however if you need
to put braces in the command, as was done in the previous lesson.
The example from the previous lesson is re-implemented in the example code using
lappend.
Example
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl33.html 1/2
9/14/2017 More command construction - format, list
set tmpFileNum 0;
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl33.html 2/2
9/14/2017 Substitution without evaluation - format, subst
The Tcl interpreter does only one substitution pass during command evaluation.
Some situations, such as placing the name of a variable in a variable, require two
passes through the substitution phase. In this case, the subst command is useful.
The format command can also be used to force some levels of substitution to occur.
If any of the -no... arguments are present, then that set of substitutions will
not be done.
Example
set a "alpha"
set b a
set num 0;
set cmd "proc tempFileName {} "
set cmd [format "%s {global num; incr num;" $cmd]
set cmd [format {%s return "/tmp/TMP.%s.$num"} $cmd [pid] ]
set cmd [format "%s }" $cmd ]
eval $cmd
set a arrayname
set b index
set c newvalue
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl34.html 1/2
9/14/2017 Substitution without evaluation - format, subst
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl34.html 2/2
9/14/2017 Changing Working Directory - cd, pwd
Tcl also supports commands to change and display the current working directory.
These are:
cd ?dirName?
Changes the current directory to dirName (if dirName is given, or to the
$HOME directory if dirName is not given. If dirName is a tilde (~, cd changes
the working directory to the users home directory. If dirName starts with a
tilde, then the rest of the characters are treated as a login id, and cd changes
the working directory to that user's $HOME.
pwd
Returns the current directory.
Example
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl35.html 1/1
9/14/2017 Debugging & Errors - errorInfo errorCode catch error return
In previous lessons we discussed how the return command could be used to return a
value from a proc. In Tcl, a proc may return a value, but it always returns a status.
When a Tcl command or procedure encounters an error during its execution, the
global variable errorInfo is set, and an error condition is generated. If you have proc a
that called proc b that called c that called d , if d generates an error, the "call stack"
will unwind. Since d generates an error, c will not complete execution cleanly, and
will have to pass the error up to b , and in turn on to a. Each procedure adds some
information about the problem to the report. For instance:
proc a {} {
b
}
proc b {} {
c
}
proc c {} {
d
}
proc d {} {
some_command
}
This actually occurs when any exception condition occurs, including break and
continue. The break and continue commands normally occur within a loop of some sort,
and the loop command catches the exception and processes it properly, meaning
that it either stops executing the loop, or continues on to the next instance of the
loop without executing the rest of the loop body.
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl36.html 1/3
9/14/2017 Debugging & Errors - errorInfo errorCode catch error return
It is possible to "catch" errors and exceptions with the catch command, which runs
some code, and catches any errors that code happens to generate. The programmer
can then decide what to do about those errors and act accordingly, instead of having
the whole application come to a halt.
For example, if an open call returns an error, the user could be prompted to provide
another file name.
A Tcl proc can also generate an error status condition. This can be done by
specifying an error return with an option to the return command, or by using the error
command. In either case, a message will be placed in errorInfo, and the proc will
generate an error.
Generates an error condition and forces the Tcl call stack to unwind, with error
information being added at each step.
If info or code are provided, the errorInfo and errorCode variables are initialized
with these values.
Evaluates and executes script. The return value of catch is the status return of
the Tcl interpreter after it executes script If there are no errors in script, this
value is 0. Otherwise it is 1.
If varName is supplied, the value returned by script is placed in varName if the script
successfully executes. If not, the error is placed in varName.
-code code
The next value specifies the return status. code must be one of:
These allow you to write procedures that behave like the built in
commands break, error, and continue.
-errorinfo info
info will be the first string in the errorInfo variable.
-errorcode errorcode
The proc will set errorCode to errorcode.
value
The string value will be the value returned by this proc.
errorInfo
errorInfo is a global variable that contains the error information from commands
that have failed.
errorCode
errorCode is a global variable that contains the error code from command that
failed. This is meant to be in a format that is easy to parse with a script, so that
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl36.html 2/3
9/14/2017 Debugging & Errors - errorInfo errorCode catch error return
Tcl scripts can examine the contents of this variable, and decide what to do
accordingly.
Example
catch errorproc
puts "after bad proc call: ErrorCode: $errorCode"
puts "ERRORINFO:\n$errorInfo\n"
catch {errorproc 2}
puts "after error generated in proc: ErrorCode: $errorCode"
puts "ERRORINFO:\n$errorInfo\n"
proc returnErr { x } {
return -code error -errorinfo "Return Generates This" -errorcode "-999"
}
catch {returnErr 2}
puts "after proc that uses return to generate an error: ErrorCode: $errorCode"
puts "ERRORINFO:\n$errorInfo\n"
catch {withError 2}
puts "after proc with an error: ErrorCode: $errorCode"
puts "ERRORINFO:\n$errorInfo\n"
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl36.html 3/3
9/14/2017 More Debugging - trace
When you are debugging Tcl code, sometimes it's useful to be able to trace either
the execution of the code, or simply inspect the state of a variable when various
things happen to it. The trace command provides these facilities. It is a very powerful
command that can be used in many interesting ways. It also risks being abused, and
can lead to very difficult to understand code if it is used improperly (for instance,
variables seemingly changing magically), so use it with care.
There are three principle operations that may be performed with the trace
command:
add, which has the general form: trace add type ops ?args?
info, which has the general form: trace info type name
remove, which has the general form: trace remove type name opList command
Which are for adding traces, retrieving information about traces, and removing
traces, respectively. Traces can be added to three kinds of "things":
variable - Traces added to variables are called when some event occurs to the
variable, such as being written to or read.
command - Traces added to commands are executed whenever the named
command is renamed or deleted.
execution - Traces on "execution" are called whenever the named command is
run.
set tracedvar 1
trace add variable tracedvar write [list vartrace $tracedvar]
set tracedvar 2
puts "tracedvar is $tracedvar"
In the above example, we create a proc that takes four arguments. We supply the
first, the old value of the variable, because write traces are triggered after the
variable's value has already been changed, so we need to preserve the original value
ourselves. The other three arguments are the variable's name, the element name if
the variable is an array (which it isn't in our example), and the operation to trace -
in this case, write. When the trace is called, we simply set the variable's value back
to its old value. We could also do something like generate an error, thus warning
people that this variable shouldn't be written to. Infact, this would probably be
better. If someone else is attempting to understand your program, they could
become quite confused when they find that a simple set command no longer
functions!
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl37.html 1/2
9/14/2017 More Debugging - trace
The command and execution traces are intended for expert users - perhaps those
writing debuggers for Tcl in Tcl itself - and are therefore not covered in this tutorial,
see the trace man page for further information.
Example
set i 2
set k $j
}
set i2 "testvalue"
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl37.html 2/2
9/14/2017 Command line arguments and environment strings
Scripts are much more useful if they can be called with different values in the
command line.
For instance, a script that extracts a particular value from a file could be written so
that it prompts for a file name, reads the file name, and then extracts the data. Or,
it could be written to loop through as many files as are in the command line, and
extract the data from each file, and print the file name and data.
The second method of writing the program can easily be used from other scripts.
This makes it more useful.
The number of command line arguments to a Tcl script is passed as the global
variable argc . The name of a Tcl script is passed to the script as the global variable
argv0 , and the rest of the command line arguments are passed as a list in argv. The
name of the executable that runs the script, such as tclsh is given by the command
info nameofexecutable
Environment variables are available to Tcl scripts in a global associative array env .
The index into env is the name of the environment variable. The command
puts "$env(PATH)" would print the contents of the PATH environment variable.
Example
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl38.html 1/1
9/14/2017 Timing scripts
Timing scripts
The simplest method of making a script run faster is to buy a faster processor.
Unfortunately, this isn't always an option. You may need to optimize your script to
run faster. This is difficult if you can't measure the time it takes to run the portion of
the script that you are trying to optimize.
The time command is the solution to this problem. time will measure the length of
time that it takes to execute a script. You can then modify the script, rerun time and
see how much you improved it.
After you've run the example, play with the size of the loop counters in timetst1 and
timetst2. If you make the inner loop counter 5 or less, it may take longer to execute
timetst2 than it takes for timetst1. This is because it takes time to calculate and assign
the variable k, and if the inner loop is too small, then the gain in not doing the
multiply inside the loop is lost in the time it takes to do the outside the loop
calculation.
Example
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl39.html 1/1
9/14/2017 Channel I/O: socket, fileevent, vwait
A stream based channel is created with the open command, as discussed in lesson 26.
A socket based channel is created with a socket command. A socket can be opened as
either as a client, or as a server.
If a socket channel is opened as a server, then the tcl program will 'listen' on that
channel for another task to attempt to connect with it. When this happens, a new
channel is created for that link (server-> new client), and the tcl program continues
to listen for connections on the original port number. In this way, a single Tcl server
could be talking to several clients simultaneously.
When a channel exists, a handler can be defined that will be invoked when the
channel is available for reading or writing. This handler is defined with the fileevent
command. When a tcl procedure does a gets or puts to a blocking device, and the
device isn't ready for I/O, the program will block until the device is ready. This may
be a long while if the other end of the I/O channel has gone off line. Using the
fileevent command, the program only accesses an I/O channel when it is ready to
move data.
Finally, there is a command to wait until an event happens. The vwait command will
wait until a variable is set. This can be used to create a semaphore style
functionality for the interaction between client and server, and let a controlling
procedure know that an event has occurred.
Look at the example, and you'll see the socket command being used as both client
and server, and the fileevent and vwait commands being used to control the I/O
between the client and server.
Note in particular the flush commands being used. Just as a channel that is opened
as a pipe to a command doesn't send data until either a flush is invoked, or a buffer
is filled, the socket based channels don't automatically send data.
Examples
set connected 0
# catch {socket -server serverOpen 33000} server
set server [socket -server serverOpen 33000]
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl40.html 2/2
9/14/2017 Time and Date - clock
The clock command provides access to the time and date functions in Tcl.
Depending on the subcommands invoked, it can acquire the current time, or convert
between different representations of time and date.
clock seconds
The clock seconds command returns the time in seconds since the epoch. The
date of the epoch varies for different operating systems, thus this value is
useful for comparison purposes, or as an input to the clock format command.
The -gmt switch takes a boolean as the second argument. If the boolean is 1
or True, then the time will be formatted as Greenwich Mean Time, otherwise, it
will be formatted as local time.
The -format option controls what format the return will be in. The contents of
the string argument to format has similar contents as the format statement (as
discussed in lesson 19, 33 and 34). In addition, there are several more %*
descriptors that can be used to describe the output.
These include:
%H . . . . Hour (00-23)
%I . . . . . Hour (00-12)
%M . . . . Minutes (00-59)
%S . . . . . Seconds(00-59)
%p . . . . . PM or AM
%D . . . . Date as %m/%d/%y
%r. . . . . Time as %I:%M:%S %p
%R . . . . Time as %H:%M
%T . . . . Time as %H:%M:%S
%Z . . . . Time Zone Name
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl41.html 1/2
9/14/2017 Time and Date - clock
If -format is not used, the command tries to guess the format of dateString,
sometimes with surprising results. It's best to use -format. The following forms
will probably return expected results:
time
A time of day in one of the formats shown below. Meridian may be AM, or
PM, or a capitalization variant. If it is not specified, then the hour (hh) is
interpreted as a 24 hour clock. Zone may be a three letter description of a
time zone, EST, PDT, etc.
date
A date in one of the formats shown below.
mm/dd/yy
mm/dd
monthname dd, yy
monthname dd
dd monthname yy
dd monthname
day, dd monthname yy
Example
puts "The book and movie versions of '2001, A Space Oddysey' had a"
puts "discrepancy of [expr {$bookSeconds - $movieSeconds}] seconds in how"
puts "soon we would have sentient computers like the HAL 9000"
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl41.html 2/2
9/14/2017 More channel I/O - fblocked & fconfigure
The previous lessons have shown how to use channels with files and blocking
sockets. Tcl also supports non-blocking reads and writes, and allows you to
configure the sizes of the I/O buffers, and how lines are terminated.
A non-blocking read or write means that instead of a gets call waiting until data is
available, it will return immediately. If there was data available, it will be read, and if
no data is available, the gets call will return a 0 length.
If you have several channels that must be checked for input, you can use the
fileevent command to trigger reads on the channels, and then use the fblocked
command to determine when all the data is read.
The fblocked and fconfigure commands provide more control over the behavior of
a channel.
The fblocked command checks whether a channel has returned all available input.
It is useful when you are working with a channel that has been set to non-blocking
mode and you need to determine if there should be data available, or if the channel
has been closed from the other end.
The fconfigure command has many options that allow you to query or fine tune the
behavior of a channel including whether the channel is blocking or non-blocking, the
buffer size, the end of line character, etc.
If a single parameter is given on the command line, the value of that parameter
is returned.
If one or more pairs of param/value pairs are provided, those parameters are
set to the requested value.
-blocking . . . Determines whether or not the task will block when data
cannot be moved on a channel. (i.e. If no data is available on a read, or
the buffer is full on a write).
-buffersize . . . The number of bytes that will be buffered before data is
sent, or can be buffered before being read when data is received. The
value must be an integer between 10 and 1000000.
-translation . . . Sets how Tcl will terminate a line when it is output. By
default, the lines are terminated with the newline, carriage return, or
newline/carriage return that is appropriate to the system on which the
interpreter is running.
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl42.html 1/3
9/14/2017 More channel I/O - fblocked & fconfigure
The example is similar to the lesson 40 example with a client and server socket in
the same script. It shows a server channel being configured to be non-blocking, and
using the default buffering style - data is not made availalble to the script until a
newline is present, or the buffer has filled.
is done, the fileevent triggers the read, but the gets can't read characters because
there is no newline. The gets returns a -1, and fblocked returns a 1. When a bare
newline is sent, the data in the input buffer will become available, and the gets
returns 18, and fblocked returns 0.
Example
if {$len < 0} {
if {$blocked} {
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl42.html 2/3
9/14/2017 More channel I/O - fblocked & fconfigure
after 120 update; # This kicks MS-Windows machines for this application
set didRead 0
puts -nonewline $sock "A Test Line"
flush $sock;
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl42.html 3/3
9/14/2017 Child interpreters
Child interpreters
For most applications, a single interpreter and subroutines are quite sufficient.
However, if you are building a client-server system (for example) you may need to
have several interpreters talking to different clients, and maintaining their state. You
can do this with state variables, naming conventions, or swapping state to and from
disk, but that gets messy.
The interp command creates new child interpreters within an existing interpreter. The
child interpreters can have their own sets of variables, commands and open files, or
they can be given access to items in the parent interpreter.
If the child is created with the -safe option, it will not be able to access the file
system, or otherwise damage your system. This feature allows a script to evaluate
code from an unknown (and untrusted) source.
The names of child interpreters are a hierarchical list. If interpreter foo is a child of
interpreter bar, then it can be accessed from the toplevel interpreter as {bar foo}.
The primary interpreter (what you get when you type tclsh) is the empty list {}.
The interp command has several subcommands and options. A critical subset is:
Note that slave interpreters have a separate state and namespace, but do not have
separate event loops. These are not threads, and they will not execute
independently. If one slave interpreter gets stopped by a blocking I/O request, for
instance, no other interpreters will be processed until it has unblocked.
The example below shows two child interpreters being created under the primary
interpreter {}. Each of these interpreters is given a variable name which contains the
name of the interpreter.
Note that the alias command causes the procedure to be evaluated in the interpreter
in which the procedure was defined, not the interpreter in which it was evaluated. If
you need a procedure to exist within an interpreter, you must interp eval a proc
command within that interpreter. If you want an interpreter to be able to call back to
the primary interpreter (or other interpreter) you can use the interp alias command.
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl43.html 1/2
9/14/2017 Child interpreters
Example
#
# A short program to return the value of "name"
#
proc rtnName {} {
global name
return "rtnName is: $name"
}
#
# Alias that procedure to a proc in $i1
interp alias $i1 rtnName {} rtnName
puts ""
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl43.html 2/2