## 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.

In the last command, $name gets substituted with var. Then the set command returns the value of var, which is the value of var. Another way to achieve a level of indirection like this is with nested set commands. The last set command above can be written as follows: 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.

### 8 The split And join Commands

The split command
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.

The
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:

The join command
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

The index of an array is delimited by parentheses. The
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)

If
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 {
I'm asking for trouble}
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

The array names command is perhaps the most useful because it allows easy iteration through an array with a foreach loop:
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 set must have the same structure.

### 11 Environment Variables

In UNIX, the process environment variables are available through the global array env.
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

The trace command lets you register a command to be called whenever a variable is accessed, modified or unset. The form is:
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

Information about traces on a varible is returned with the vinfo option.
trace vinfo dynamic
=> {r FixDynamic}
A trace is deleted with the vdelete trace option, which has the same form as the varible option.