rcubefather
rcubefather

Reputation: 1564

how to make a variable global inside a while loop

Following is the TCL script to print numbers between 1 to 10 using while loop.

set b 1

while {$b<11} {
    puts $b
    incr b
}

In the above script, how to make "puts $b" output as global. So that we can use this where ever we want in the script?

I need the following:

set b 1

while {$b<11} {
    set a $b
    incr b
}

puts "This is number $a"

If I use $a in outside loop, it should print the output as :

This is number 1
This is number 2
This is number 3
.
.
.
This is number 10

Upvotes: 1

Views: 1269

Answers (2)

Peter Lewerin
Peter Lewerin

Reputation: 13252

Your question isn't entirely clear: I think Donal Fellows may have given you the right answer, but I think I may see another question lurking in your text, namely: how can I write a generic command that will, as it were, take a variable for a brief spin?

As in:

set b 1

myLoop b {
    set a $b
    puts "This is number $a"
}
puts "Again, this is number $a"

You would write myLoop like this:

proc myLoop {varName body} {
    upvar 1 $varName i
    for {} {$i < 11} {incr i} {
        uplevel 1 $body
    }
}

Note that this is not the best way to write a command like this: I'm writing it this way to accommodate your example code.

The command works by calling uplevel to evaluate the script in body in the context of the caller, whichever that is. To allow myLoop to manipulate the variable in the script, we need to set up things so that the command will share the variable with the caller. The upvar command does that.

Upvotes: 0

Donal Fellows
Donal Fellows

Reputation: 137567

Tcl is really strictly operational; it does things at the point where you tell it to. However, one of the things that you can do is to put a trace on a variable so that some code gets run whenever the variable is written to.

# This is Tcl 8.5 syntax; let me know if you want it for 8.4 and before
trace add variable ::a write {apply {args {
   puts "This is number $::a"
}}}

I've used fully-qualified variable names above; the trace is really on the variable a in the namespace ::.
Then, after setting the trace, when we do:

set b 1

while {$b<11} {
    set a $b
    incr b
}

The output then is:

This is number 1
This is number 2
This is number 3
This is number 4
This is number 5
This is number 6
This is number 7
This is number 8
This is number 9
This is number 10

Which is what you wanted.

Upvotes: 3

Related Questions