|
|
|
|
|
|
|
|
|
|
|
Variables
|
|
|
Simple variables have a name and a value (stored as a string). |
|
|
|
|
|
Arrays are a collection of elements, each of which is a variable with it own name and value. Array names and element names may be arbitrary strings (i.e. sometimes called associative arrays to distinguish them from arrays that require elements to be integers). |
|
|
|
|
|
Example: |
|
|
|
|
|
set yearTotal 0 |
|
|
|
|
|
foreach month {Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec} { |
|
|
|
|
|
set yearTotal [expr $yearTotal+$earnings($month)] |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
Tcl only implements one-dimensional arrays, but multidimensional arrays are simulated by concatenating multiple indices into a single element name. |
|
|
|
|
|
set matrix(1,1) 140 |
|
|
|
|
|
set matrix(1,2) 218 |
|
|
|
|
|
set matrix(1,3) 84 |
|
|
|
|
|
set i 1 |
|
|
|
|
|
set j 2 |
|
|
|
|
|
set cell $matrix($i,$j) |
|
|
|
|
|
=> 218 |
|
|
|
|
|
*Note that there are no spaces because the three element names are 1,1 and 1,2 and 1,3. Thus: |
|
|
|
|
|
matrix(2,5) |
|
|
|
|
|
|
|
|
is not the same as |
|
|
|
|
|
matrix(2, 5) |
|
|
|
|
|
|
|
|
Expressions
|
|
|
Expressions combine operands and operators to create new values. |
|
|
|
|
|
Syntax: expr arg ?arg arg ...? |
|
|
|
|
|
|
|
|
Operators
|
|
|
|
|
|
* Relational operators (<, <=, >, >=, ==, !=) return 0 (false) or 1 (true). |
|
|
* Bitwise operators (&, |, ^, <<, >>, ~) require operands to be integers. |
|
|
|
|
|
<< and >> use the right operand as the shift count (in bits). During left shifts, zeros are shifted into the low order bytes. Right shifts are "arithmetic right shifts" which shifts zeros for positive number, and ones for negative numbers (unlike ANSI C which is machine dependent). The ~ is a one's complement operator that flips each bit. |
|
|
* Choice operator is the ternary operator ?: if first operand is true, evaluate the second operand, otherwise evaluate the third operand. |
|
|
|
|
|
Syntax: expr { ($a < $b) ? $a : $b} |
|
|
|
|
|
Substitutions
|
|
|
|
|
|
Substitutions can occur in two ways for expression operands. |
|
|
|
|
|
1. Through the normal Tcl parser mechanism |
|
|
2. Through expression evaluator which performs an additional round of variable and command substitutions on the expression while evaluating it. |
|
|
|
|
|
Example: |
|
|
|
|
|
expr { 2*sin($x) } |
|
|
|
|
|
The braces causes Tcl parser to not do a variable substitution for x. When the expression evaluator encounters the dollar sign, it performs variable substitution itself. This is not very useful for the exprcommand, but is useful for other commands like while that evaluate an expression repeatedly and expect to get a different result each time. |
|
|
|
|
|
Example: |
|
|
|
|
|
set pow 1 |
|
|
|
|
|
while {$pow<$num} { |
|
|
|
|
|
set pow [expr $pow*2] |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
If the braces were omitted in {$pow<$num}, the while's argument would be a constant expression such as 1<44 which would cause in infinite loop. |
|
|
|
|
|
String manipulation
|
|
|
|
|
|
Tcl allows string operands for some operators: <, >, <=, >=, ==, and !=. For all other operators, the operands must be numeric. Tcl only uses string comparisons if one or both of the operands cannot be parsed as a number. |
|
|
|
|
|
Example: |
|
|
|
|
|
set x 0 |
|
|
|
|
|
set y 00 |
|
|
|
|
|
if {$x==$y} { |
|
|
|
|
|
... |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
Arithmetic comparison will be used and the test will evaluate to 1. To force string comparison for numeric operands, use a command such as string compare. |
|
|
|
|
|
Types and conversions
|
|
|
|
|
|
Tcl evaluates expressions numerically whenever possible. String operations are performed only for the relational operators and only if one or both of the operands doesn't make sense as a number. Automatic conversion is done for operands of different types: |
|
|
|
|
|
* real and int: int => real |
|
|
* non-numeric string and int/real: int/real => string |
|
|
|
|
|
Also, use double, and int and round to cast int to real and real to int respectively. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Precision
|
|
|
|
|
|
- integers (type int): 32 bits precision
- real (type double): 64 bits precision
- numbers are kept in internal form throughout evaluation of an expression and are only converted back to strings when necessary
- conversion of real to string defaults to 6 significant digits. Setting Tcl global variable tcl_precision can change significant digits. Note: setting tcl_precision to 17 on a machine that uses IEEE floating point will guarantee that string conversions do not lose information (e.g. when an expression is converted to string and then used in a numeric calculation later).
|
|
|
|
|
|
List
|
|
|
A list is an ordered collection of elements (separated by spaces) where each element can have any string value. Lists can be nested. |
|
|
|
|
|
Command
|
Result
|
concat ?list list ...?
|
Joins multiple lists into a single list (each element of each list becomes an element of the result list) and returns the new list.
|
join list ?joinString?
|
Concatenates list elements together with joinString as separator and returns the result. joinString defaults to a space.
|
lappend varName value ?value ...?
|
Appends each value to variable varName as a list element and returns the new value of the variable. Creates the variable if it doesn't exist.
|
lindex list index
|
Returns the index'th element from list (0 refers to the first element).
|
linsert list index value ?value ...?
|
Returns a new list formed by inserting all of the value arguments as list elements before index'th element of list (0 refers to the first element).
|
list ?value value ...?
|
Returns a list whose elements are the value arguments.
|
llength list
|
Returns the number of elements in list.
|
lrange list first last
|
Returns a list consisting of elements first through last of list. If last is end, it selects all elements up to the end of list.
|
lreplace list first last ?value value ...?
|
Returns a new list formed by replacing elements first through last of list with zero or more new elements, each formed from one value argument.
|
lsearch ?-exact? ?-glob? ?-regexp? list pattern
|
Returns the index of the first element in list that matches pattern or -1 if none. The optional switch selects a pattern-matching technique (default : -glob).
|
lsort ?-ascii? ?-integer? ?-real? ?-command command? ?-increasing? ?-decreasing? list
|
Returns a new list formed by sorting the elements of list. The switches determine the comparison function and sorted order (default : -ascii -increasing).
|
split string ?splitChars?
|
Returns a list formed by splitting string at instances of splitChars and turning the characters between these instatnces into list elements.
|
|
|
|
|
|
|
Control Flow
|
|
|
|
|
|
Command
|
Result
|
if test1 body1 ?elseif test2 body2 elseif ...? ?else bodyn?
|
|
while test body
|
|
for init test reinit body
|
|
foreach varName list body
|
|
switch ?options? string pattern body ?pattern body ...?, switch ?options? string { pattern body ?pattern body ...? }
|
Options : -exact (exact matching), -glob (same as string matching), or -regexp (regular expression matching). If a script is '-', switch use the script for next pattern (i.e. several patterns can all execute the same script). default pattern used to catch unmatched patterns.
|
eval arg ?arg arg ...?
|
General purpose building block for creating and executing Tcl scripts. It accepts any number of arguments, concatenates all of the args with separator spaces, then evaluates the result as a Tcl script and returns its results which is useful when you need to force another level of parsing.
|
|
|
|
|
|
|
Procedures
|
|
|
|
|
|
Procedures are normal Tcl commands that are useful in packaging modules that can be reused. Procedures can be defined at any time and you can pass arguments by value or by reference. The value returned is the result of the last statement in the body of the procedure, unless explicitly returned with the return command. |
|
|
|
|
|
Syntax: |
|
|
|
|
|
proc procedure_name arguments ?args? body |
|
|
|
|
|
e.g.: |
|
|
|
|
|
proc plus {a b} {expr $a+$b} |
|
|
|
|
|
Arguments
|
|
|
|
|
|
Arguments used inside a procedure are local. To reference global variables, the global command will bind variables within the procedure for the life of the procedure. Arguments can have default values and are specified as follows: |
|
|
|
|
|
proc inc {value {increment 1}} { |
|
|
|
|
|
expr $value+$increment |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
incr 42 3 |
|
|
|
|
|
=> 45 |
|
|
|
|
|
|
|
|
|
|
|
incr 42 |
|
|
|
|
|
=> 43 |
|
|
|
|
|
Defaulted arguments, if any, must be the last arguments for the procedure. If a default is not specified, the argument is required. |
|
|
|
|
|
Variable number of arguments is supported by args which is put at the end of the argument list. The procedure uses the args argument as a list whose elements are the extra arguments. If there are no extra arguments, args will be set to an empty string. |
|
|
|
|
|
proc sum args { |
|
|
|
|
|
set s 0 |
|
|
|
|
|
foreach i $args { |
|
|
|
|
|
incr s $i |
|
|
|
|
|
} |
|
|
|
|
|
return $s |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
sum 1 2 3 4 5 |
|
|
|
|
|
=> 15 |
|
|
|
|
|
|
|
|
|
|
|
sum |
|
|
|
|
|
=> 0 |
|
|
|
|
|
Call by reference
|
|
|
|
|
|
The upvar command provides a general mechanism for accessing variables outside the context of a procedure. It can be used to access global or local variables in some other active procedure, but is most often used to pass in arrays (because there is no value for an array, just its elements). |
|
|
|
|
|
Example: |
|
|
|
|
|
proc parray name { |
|
|
|
|
|
upvar $name a |
|
|
|
|
|
foreach el [lsort [array names a]] { |
|
|
|
|
|
puts "$el = $a($el)" |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
set info(age) 37 |
|
|
|
|
|
set info(position) "Vice President" |
|
|
|
|
|
parray info |
|
|
|
|
|
=> age = 37 |
|
|
|
|
|
position = Vice President |
|
|
|
|
|
upvar can also be used to access variables on different levels of the call stack. |
|
|
|
|
|
upvar #0 other x |
|
|
|
|
|
makes global variable other accessible via local variable x (#0 specifies access to the global variable other regardless of the level of the call stack). |
|
|
|
|
|
upvar 2 other x |
|
|
|
|
|
makes variable other in the caller of the caller of the current procedure accessible as local variable x (2 specifies two levels up in the call stack). |
|
|
|
|
|
Creating new control structures
|
|
|
|
|
|
uplevel is a command that is a cross between eval and upvar. It evaluates its argument(s) as a script, just like eval, but the script is evaluated in the variable context of a different stack level like upvar. With uplevel, you can define new control structures as Tcl procedures. |
|
|
|
|
|
Example: |
|
|
|
|
|
proc do {varName first last body}{ |
|
|
|
|
|
upvar $varName v |
|
|
|
|
|
for {set v $first} {$v <= $last} {incr v} |
|
|
|
|
|
uplevel $body |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
set squares {} |
|
|
|
|
|
do i 1 5 { |
|
|
|
|
|
lappend squares [expr $i*$i] |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
set squares |
|
|
|
|
|
=> 1 4 9 16 25 |
|
|
|
|
|
Like upvar, uplevel takes an optional inital argument that specifies an explicit stack level. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|