A couple of things to add here...
First of all, I noticed the code fragment that
Bong provided for handling a list of global variable names passed as an argument to a procedure:
Code:
set cmd "global"
foreach var $gblst {append cmd " $var"}
eval $cmd
A much better way to accomplish the same thing would be simply:
The
eval command concatenates all of its arguments (just like the
concat command), and then executes the resulting list. An alternate way that I explain how
eval works (especially for those who aren't comfortable with the idea of treating a list as a command) is that it's similar to breaking down one level of list structure in each of its arguments, and then executing the result.
As to the main point of the discussion, I agree that either approach is appropriate, depending on the application. In general, I'll use the approach that's clearest and easiest to maintain. Given that criteria, I tend to prefer globals when there's a lot of information to pass around, just to keep from cluttering up the argument list for all of the procedures.
But if you've got a lot of values, it's better to use a single array to pass around all of the values, rather than cluttering up the global scope with a bunch of variables. For example:
Code:
array set state {
active 1
ip 127.0.0.1
name WaffleServer
}
proc process {} {
global state
# ...
}
Something else you might want to consider if you've got a lot of values that you're passing around is to use Tcl namespaces to help segregate your data and prevent variable name clashes.
A side note: Because of Tcl's implementation in 8.0 and beyond, passed parameters should be
slightly faster than globals if you use the value only once or twice inside the procedure. The reason: When passing a parameter to a procedure, internally Tcl passes just a reference to a shared object representing the value. If you don't try to modify the value in any way (for example, assigning it to a variable and then incrementing the variable), then Tcl never needs to make a duplicate of the value, which saves some time. On the other hand, when you explicitly declare a global variable within a procedure, Tcl needs to do a lookup in the internal global variable hash table, and then create a reference to the variable in the procedure's reference table. Most of the time, the difference is far too small to be noticed. But if you're trying to squeeze out every microsecond you can, it's nice to know. Here's some timing comparisons on my IBM Thinkpad T20, a 750MHz Pentium III with 192MB of RAM running Tcl 8.3.2 on Windows 2000:
[tt]%
set a 42
42
%
proc test1 {val} {
>
}
%
proc test2 {} {
>
global a
>
}
%
time {test1 $a} 100000
4 microseconds per iteration
%
time {test2} 100000
16 microseconds per iteration[/tt]
- Ken Jones, President
Avia Training and Consulting
866-TCL-HELP (866-825-4357) US Toll free
415-643-8692 Voice
415-643-8697 Fax