Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

When to use globals vs. parameters 1

Status
Not open for further replies.

Bong

Programmer
Dec 22, 1999
2,063
US
Greeting.
Let's say I have a dozen or so proc's using many of the same variables from main. Is there any reason to prefer global variables over parameters (aka arguments) passed into the proc? Globals are certainly easier in some sense since I can define a list (gblst) of variable names in main, pass the list as a parameter and build a global command (set cmd "global"; foreach var $gblst {append cmd " $var}; eval $cmd) inside each proc. The question is, is there a performance or efficiency problem?
 
I had a problem like this with data structures in tcl
and expect and was wondering if there was any big
difference.

As far as I can tell it is a matter of preference.
Using parameters to the proc and working the stack
is more "fun", for me and less cluttered than having
a:
proc foo {} {
global A B C D E F
etc..
}

Brent Welch gives some examples of operations like this
using arrays and lists as data structures in TCL/TK and
notes that after tcl 8.0 there really is very little
performance difference in the methods used.

 
Thanks. That's what I sort of figured. I like "working the stack" too but sometimes the argument list can get pretty long. Bob Rashkin
rrashkin@csc.com
 
Globals are easy to use but more difficult to manage:
They can be modified anywhere in your code, out of context.

For example:
Two variables can retain the state of objects and some mixt of states can have no meaning.
With globals it is very easy to access only one variable and make a mistake.
Avoiding globals you can modify these variables thru procs that verify the consistency of the states.

But if you have clearly defined contexts where to use globals, don't hesitate.

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

Code:
eval global $gblst

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
 

Linux 2.4.14 700mhz/tbird 256mb RAM

test1 == identical, 4ms per iteration
test2 == different, 15ms per iteration

Very noticeable too..

Thanks Avia.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top