Joshua
Joshua

Reputation: 4320

TCL global stumping me

I have a script where I am doing what appears to be the exact same thing, but it works in that one and not this one. I'm hoping that a few more pairs of eyes will be able to help me find out the issue, I've already spent an hour and a half on it.

I have a proc that edits the global var, it's more complex that this but I'll use this for simplicity's sake:

proc myCustomProc { var } {

global __myGlobal
set __myGlobal [ expr $__myGlobal + 1 ]
}

I have defined a variable globally in my "main" proc:

proc FOO {} {
global __myGlobal
...
...
myCustomProc 5
puts $__myGlobal

Then I get can't read "__myGlobal": no such variable

I have the exact code with a different varname working in a different script, so I'm stumped. Obviously it's NOT identical, I just cannot find the issue.

Edit: both procs are in the same .tcl file

Upvotes: 0

Views: 183

Answers (2)

Bryan Oakley
Bryan Oakley

Reputation: 386352

The short answer is, you are using $__myGlobal in the expr command before it has been set.

Upvotes: 0

Donal Fellows
Donal Fellows

Reputation: 137787

You can't read from a variable that is unset, and that's true whether that variable is global or not. Thus, in the code:

set __myGlobal [ expr $__myGlobal + 1 ]

It first reads the value from the global variable, then adds one to that value, then writes the result back to the global variable. (Actually, it is interpreting the contents of the variable as an expression fragment, which I'd lay good money on being something you don't want as it is slow and unsafe; put the whole expression in braces please.)

For adding one to an integer (and from Tcl 8.5 onwards) you should just use the incr command instead, as that interprets a non-existent value as if it was zero:

incr __myGlobal

But if you're doing something more complex (or working in 8.4 or before), you should instead put a check with info exists like this in front:

if {![info exists __myGlobal]} {
    set __myGlobal "the default value";    # Or whatever default you want
}

You could also use a more complex expression like this:

set __myGlobal [expr {[info exists __myGlobal] ? $__myGlobal+1 : 1}]

But I usually try to avoid the ternary operator; it's often not that readable.

Upvotes: 2

Related Questions