proc f {varname} {
upvar 1 $varname var
set var ...somevalue...
}
The upvar “links” the local variable var to the variable named $varname in the scope of the calling function. Or maybe you are in dire need of a control construct that loops thrice? No problem: proc do_thrice {code} {
foreach _ {1 2 3} {
uplevel 1 $code
}
}
Okay, this does not handle break, continue or error propagation (you can do that also, but it would be a bit longer). You can use this like so: set text Go!
do_thrice {puts $text}
The variable text is not visible inside of do_thrice; but the uplevel executes the code in the scope of its caller, so it can read and write to the local variables just like an ordinary loop.Of course, in ordinary code you should mostly avoid this kind of stuff. Though apparently uplevel is used by NASA, of all people, so I guess it is fine!
More fun stuff: You use the built-in proc to define a new procedure, but you can replace it by your own, e.g. to insert profiling code at beginning and end. (Hint: If you try this, use uplevel when calling the built-in proc, to avoid namespace problems.) You can parse and rewrite code at runtime (of course) which I once used to insert “breakpoints” at runtime for my program to debug itself.