I have a procedure that use a global dictionary. it is a global one because I need the procedure to be able to read inside the dictionary and update it.
I need to be able to use either this global dictionary dict_glob1
or another dictionary dict_glob2
depending on a argument of the procedure.
I could provide as argument the correct dictionary but then I'm afraid I won't be able to update it. In fact I guess I need to be able to provide only the "name" of the global dictionary. but I don't know how to link the "name" of the dictionary with the real dictionary inside the procedure.
The easiest method is to use upvar
(plus whatever logic you need to decode the argument) to give the variable you want to access/update a consistent local name within your procedure. That keeps the complexity in the vicinity of setting up the upvar
call; everything after that is simple (or at least just as complex as it needs to be).
Here's a contrived version (d
is just a local variable name that's a bit mnemonic for "dictionary"):
proc doTheThing {{argument "foo"}} {
if {$argument eq "foo"} {
upvar "#0" dict_glob1 d
} else {
upvar 1 dict_glob2 d
}
dict set d abc 123
}
It's more normal for variable names to be always passed as arguments by the caller. They can name global variables if they want. In that case, you'd get:
proc doTheThing {{varName "::dict_glob1"}} {
upvar 1 $varName d
dict set d abc 123
}
In this case, we're naming a global variable as a default argument, but the caller can override it to be any other name (either namespaced or in their scope) that they prefer it to be.