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 interpreter. Other commands allowing introspection involve: traces, namespaces, commands scheduled for later execution via the after command and so on.
Here we explain 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 command that throws a no such variable error, since it checks to be certain that the variable exists before incrementing it (the core command initialises the variable to zero instead):
proc nitpickyIncr {val {amount 1}} { upvar $val v if { [info exists v] } { incr v $amount } else { return -code error "Variable $val does not exist!" } }
Almost all the info subcommands 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 "*").
# # Use the catch command to prevent the program from ending # prematurely, and demonstrate a simple use of [info procs] # if {[info procs nitpickyIncr] eq "nitpickyIncr"} { catch { nitpickyIncr a } msg } else { puts "Please define the procedure 'nitpickyIncr'" exit } puts "After calling nitpickyIncr with a non existent variable:" puts "$msg" set a 100 nitpickyIncr a puts "After calling nitpickyIncr with a variable with" puts "a value of 100: $a" catch { nitpickyIncr b -3 } msg puts "After calling nitpickyIncr with a non existent variable" puts "by -3: $msg" set b 100 nitpickyIncr b -3 puts "After calling nitpickyIncr with a variable whose value" puts "is 100 by -3: $b" puts "\nThese variables have been defined:\n[lsort [info vars]]" puts "\nThese globals have been defined:\n[lsort [info globals]]" set exist [info procs localproc] if {$exist == ""} { puts "\nlocalproc does not exist at point 1" } proc localproc {} { global argv set loc1 1 set loc2 2 puts "\nLocal variables accessible in this proc are:" puts " [lsort [info locals]]" puts "\nVariables accessible from this proc are:" puts " [lsort [info vars]]" puts "\nGlobal variables visible from this proc are:" puts " [lsort [info globals]]" } set exist [info procs localproc] if {$exist != ""} { puts "localproc does exist at point 2" } localproc
(Note: Some lines have been abbreviated to make them fit.)
After calling nitpickyIncr with a non existent variable: Variable a does not exist! After calling nitpickyIncr with a variable with a value of 100: 101 After calling nitpickyIncr with a non existent variable by -3: Variable b does not exist! After calling nitpickyIncr with a variable whose value is 100 by -3: 97 These variables have been defined: a argc argv argv0 auto_path b env errorCode errorInfo msg ... These globals have been defined: a argc argv argv0 auto_path b env errorCode errorInfo msg ... localproc does not exist at point 1 localproc does exist at point 2 Local variables accessible in this proc are: loc1 loc2 Variables accessible from this proc are: argv loc1 loc2 Global variables visible from this proc are: a argc argv argv0 auto_path b env errorCode errorInfo ...