Part III Tcl Data Structures
1 More about Variables
- The set command
The
set
command is used to define variables of any type. In addition, the set
command will return the value of a variable if it is only passed a
single argument. It treats that argument as a variable name and returns
the current value of the variable.
set [set name]
=> the value of var
- The unset command
You can delete a variable with the unset command:
unset
varName varName2 ...
- Using info to find out about variables
The existence of a variable can be tested with the info exists command.
e.g.
if ![info exists foobar]{
set foobar 0
} else {
incr foobar }
2 Tcl Lists
The Tcl list has the same structure as a Tcl command. That is, a
list is simply a string with list elements separated by white
space.Braces or quotes can be used to group words with whitespace into
a single list element.
3 Constructing Lists: list , lappend and concat
The
list
command constructs a list out of its arguments such that there is one
list element for each argument. if any of the arguments contain special
characters, the list command adds some quoting to ensure they are
parsed as a single element of the resulting list.
e.g.
Constructing a list with the
list
command
set x {1 2}
=> 1 2
set x
=> 1 2
list $x /$ foo
=> {1 2} {$} foo
[Note]: The braces used to group the list value into one argument to the set command are not part of the list value.
The
lappend
command is used to append elements to the end of a list. You can call
lappend
with the name of an undefined variable and the variable will be created.
e.g.
lappend new 1 2
=> 1 2
lappend new 3 "4 5"
=> 1 2 3 {4 5}
set new
=> 1 2 3 {4 5}
The
concat
command is useful for splicing together lists. It works by
concatenating its arguments together, separating them with spaces. This
multiple lists into one where the top-level list elements in each input
list are also top-level list elements in the resulting list.
e.g.
Using
concat
to splice together lists.
concat 1 {2 3} {4 5 6}
=> 1 2 3 4 5 6
It turns out that double quotes behave much like the
concat
command.
e.g.
Double quotes compared to the
list
command.
set x {1 2}
=> 1 2
set y "$x 3"
=> 1 2 3
set y [concat $x 3]
=> 1 2 3
set z [list $x 3]
=>{1 2} 3
The basic rule is that
list
and
lappend
preserve preserve list structure, while
concat
(or double-quotes)eliminate one level of list structure.
4 Getting List Elements: llength, lindex, and lrange
The
llength
command returns the number of elements in a list.
The
lindex
command returns a particular element of a list. It takes an index. List indices count from zero. The keyword
end
means the last element, and it can be used with
lindex, linsert, lrange
and
lreplace
.
e.g.
lindex {1 2 3} 0
=> 1
lindex {1 2 3} 2
=> 3
The
lrange
command returns a range of list elements. It takes a list and two indices as arguments.
e.g.
lrange {1 2 3 {4 5}} 2 end
=> 3 {4 5}
5 Modifying Lists: linsert and lreplace
The
linsert
command inserts elements into a list value at a specified index. If the
index is 0 or less, then elements are added to the front. If the index
is equal to or greater than the length of the list, then the elements
are appended to the end. Otherwise, the elements are inserted before
the element that is currentl as position index.
lreplace
is used to replace a range of list elements with new elements. If you
don't specify any new elements, you effectively delete elements from a
list.
e.g.
linsert {1 2} 0 new stuff
=> new stuff 1 2
set x [list a {b c} e d]
=> a {b c} e d
lreplace $x 1 2 B C
=> a B C d
lreplace $x 0 0
=> {b c} e d
6 Searching Lists: lsearch
lsearch
returns the index of a value in the list, or -1 if it is not present.
lsearch
supports pattern matching in its search. Glob-style pattern matching is default, and this canbe disabled with the
-exact
flag.
The example below uses
lreplace
to delete elements by not specifying any replacement list elements.
e.g.
proc delete {list value} {
set ix [lsearch -exact $list $value]
if {$ix>=0} {
return [lreplace $list $ix $ix]
} else {
return $list
}
}
7 Sorting List: lsort
The three basic types of sorts are specified with the
-ascii, -integer
, or
-real
options. The
-increasing
or
-decreasing
option indicate the sirting order. The default option set is
-ascii -increasing
.
The
split
command
The
The
join
command
The index of an array is delimited by parentheses. The
If
The array names command is perhaps the most useful because it allows easy iteration through an array with a foreach loop:
In UNIX, the process environment variables are available through the global array
env
.
The trace command lets you register a command to be called whenever a variable is accessed, modified or unset. The form is:
Information about traces on a varible is returned with the vinfo option.
8 The split And join Commands
takes a string and turns it into a list by breaking it at specified
characters. Stray double-quotes or curly braces in the input can result
in invalid list structures and errors in your script. However, the
split command provides a robust way to turn input lines into proper Tcl
lists.
default split character is white space. If there are multiple separator
characters in a row, these result in empty list elements- the
separators are not collapsed. The following command splits on commas,
periods, spaces and tabs:
is the inverse of split. It takes a list value and reformats it with
specified characters separating the list elements. In doing so, it will
remove any curly braces from the string representation of the list that
are used to group the top-level elements.
9 Arrays
index can have any string value, and it canbe the result of variable or
command substitution.
e.g.
set arra(
index
) value
The value of an array element is obtained with $ substitution:
e.g.
set foo $arr(
index
)
you have complex indices, use a comma to separate different parts of
the index. Avoid putting a pace after the comma. It is legal, but a
space in an index value will cause problems because parenthesis are not
used as a grouping mechanism. The space in the index needs to be quoted
with a backslash, or hte whole variable reference needs to be grouped:
e.g.
set {arr(I'm asking for trouble)} {I told you so.}
If
the array index is stored in a variable, then there is no problem with
spaces in the variable's value. The following works fine:
e.g.
set index {
set arr($index) {
I told you so.
}
The
name of the array can be the result of a substitution. If the name of
the array is stored in another variable, then you must use set as shown
in the last command below to reference the array elements.
10 The Array Command
foreach index [array names arr] {command body}
The order of the names returned by array names is
arbitrary. It is essentially determined by the hash table
implementation of the array.
The
array get
and
array set
operations are used to convert between an array and a list. The list returned by
array get
has an even number of elements.The first element is an index, and the
next is the corresponding array value. The ordering of the indexes is
arbitrary. The list argument to
array se
t must have the same structure.
11 Environment Variables
The name of the environment variable is the index,e.g. env(PATH), and
the array element contains the current value of the environment
variable.
12 Tracing Variable Values
trace
variable name ops command
The name is a Tcl variable name, which can be a simple
variable, an array or a element.If a whole array is traced, then the
trace is invoked when any element is used according to ops. The ops
argument is one or more of the letters: r for read traces, w for write
traces, and u for unset traces. The command is executed when one of
these events occurs. It is invoked as:
command name1 name2 op
trace vinfo dynamic
=> {r FixDynamic}
A trace is deleted with the
vdelete
trace
option, which has the same form as the
varible
option.