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 Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Setting A Variable Number Of Global Variables

Status
Not open for further replies.

cptk

Technical User
Mar 18, 2003
305
0
0
US
At startup, the application reads in a text file and uses some of the settings to help create Checkboxes within a grid. The text file contents can vary, thus the number of checkboxes created will vary as well. The checkboxes are built in the main portion of the program (i.e. -outside of any proc), but I need to use their -variable option value in a proc, thus I need to globally set each of the checkboxe's -variable options within the proc. HOW DO YOU WORK WITH VARING NUMBER OF VARIABLES GLOBALLY? ...thanks!
 
I've gotten closer (thanks to a previous search and reply from "ULIS"), but ...

I can't seem to finalize it!!

How do I "build" a variable using the "::"?
Ex: $::cbv$w
where $w equals "OPT1"
- it gives me an error "can't read "::cbv"; no such variable

Hardcoding the $::cbvOPT1 works great though.
 
I would use list and lappend:

read the text file into a list of variable names, say, vlist
then:

foreach var $vlist {lappend globalst cbv$var}

then, in your proc:
global gblst
eval global $gblst


Bob Rashkin
rrashkin@csc.com
 
I meant:
foreach var $vlist {lappend gblst cbv$var}
sorry:-(



Bob Rashkin
rrashkin@csc.com
 
Thanks, but I tried that and it's not giving me what I need.

That method still requires me to set value explicitly, like:
$::cbvOPT1

What I want to do is to be able to subsitute a portion of the global variable, like $::cbv$w
This should be easy, but I'm "blocked" right now ...
 
I assume you need to use the global -onvalue value of a checkbox?

I think this might resolve your problem, provided you incorporate Bong's advice.

> global gblst
> eval global $gblst

> foreach x $gblst {
> .info_display insert end "[expr $$x]\n"
> }

By the way, if you use instead "eval" in place of "expr", it will attempt to execute the return value of the -onvalue(due to the []'s), which is not what you exactly need. Here, the expr gives you what you need. I never could figure the difference betw. the two, if someone could elaborate, fell free. Hope this helps!
 
You can set easily a variable with a composed name:
Code:
set ::cbv$w 1234
But, for referencing it, you need a more complex syntax because this doesn't work:
Code:
set a $::cbv$w
With such a line Tcl searches for the value that is the concatenation of the values of the global variable ::cbv and of the local variable w. Not for the value of the global variable ::cbv$w (whose name is the concatenation of the string ::cvb with the value of w).
In other words, Tcl sees [$::cbv][$w} and not $[::cbv$w].
To do the trick you need to use the old syntax to get the value of your variable with a composed name:
Code:
set a [set $::cbv$w]

From the manual page:
Code:
set varName ?value?
Returns the value of variable varName. If value is specified, then set the value of varName to value, creating a new variable if one doesn't already exist, and return its value.

HTH

ulis
 
Sorry, I should say:
Code:
set a [set ::cbv$w]

ulis
 
This is really much easier if you use a global array rather than separate global variables. The -variable attribute can accept an element of a global array (as can the -textvariable attribute supported by many widgets and the -listvariable attribute supported by the listbox). Then you have a single global declaration in your procedures. For example:

Code:
checkbutton .cb1 -text "Choice 1" -variable values(val1)
checkbutton .cb2 -text "Choice 2" -variable values(val2)
checkbutton .cb3 -text "Choice 3" -variable values(val3)
checkbutton .cb4 -text "Choice 4" -variable values(val4)
checkbutton .cb5 -text "Choice 5" -variable values(val5)
pack .cb1 .cb2 .cb3 .cb4 .cb5

proc myProc {} {
  global values
  foreach elem [lsort [array names values]] {
    puts "values($elem) = $values($elem)"
  }
}


- Ken Jones, President, ken@avia-training.com
Avia Training and Consulting, 866-TCL-HELP (866-825-4357) US Toll free
415-643-8692 Voice
415-643-8697 Fax
 
Ken -
That's almost what I did while experimenting over the weekend. I already have a "two-dimensional" opt_array set-up, so all I did was add another element (i.e. - CBstate) to that array when I set the -variable value of the checkbox widget.
> foreach $x $option_list
> -variable opt-array($x, CBstate)

Since opt_array is defined outside any proc stmt (what do you typically call this area when it's outside any procs - main area?) and I'm also defining the checkboxes outside the main area, when I need to see the "state" of a checkbox within a proc, I just refer to the global opt_array variable, which will have the CBstate element. This keeps it simple and efficient!
Thanks for the response ...
 
I usually refer to code outside of any procedures as being in the global scope. (Unless it's inside of a namespace block, in which case I cringe a bit and call it the namespace scope because I don't know what else to call it.) I'm not a formal computer linguist, so I don't get too hung up on the terms I'm using as long as everyone knows what I'm talking about. :)

As an aside for those people who might not be aware of it, it's legal for a Tcl procedure to create a new global variable. For example:

Code:
proc init {} {
    global state
    set state "disconnected"
}

# ...

init

This is particularly handy for libraries of Tcl code, when you need to initialize the state of the library code before executing other library procedures. Also, I know that some programmers who come from a C/C++ background like to create a main procedure in their Tcl code, and then explicitly call main to start their application running.

This can actually provide a slight performance advantage, especially if you've got one or more loops that will run many iterations. Tcl procedures are bytecode-compiled, and thus they can run faster than global, uncompiled code. But it doesn't make much difference unless there's a lot of code to run, like the long loops I mentioned above:

Code:
% time {
    for {set i 0} {$i < 100000} {incr i} {
        lappend list1 [expr { rand()*20000 - 10000 }]
    }
}
310138 microseconds per iteration
% proc init {} {
    global list2
    for {set i 0} {$i < 100000} {incr i} {
        lappend list2 [expr { rand()*20000 - 10000 }]
    }
}
% time { init }
165162 microseconds per iteration

- Ken Jones, President, ken@avia-training.com
Avia Training and Consulting, 866-TCL-HELP (866-825-4357) US Toll free
415-643-8692 Voice
415-643-8697 Fax
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top