Crée un lien vers une variable dans un cadre de pile différent
upvar ?level? otherVar myVar ?otherVar myVar...?
Cette commande prépare une ou plusieurs variables locales dans la fonction courante à se référer à des variables dans un appel de fonction externe ou à des variables globales. level peut avoir quelconque des formes permises pour la commande uplevel, et peut être omis si la première lettre de la première otherVar n'est pas # ou un chiffre (il est par défaut de 1).
Pour chaque argument otherVar, upvar rend la variable de ce nom dans le cadre de fonction indiqué par level (ou au niveau global, si niveau est #0) accessible dans la fonction courante par le nom donné dans l'argument correspondant myVar. Le nom de variable otherVar n'a pas besoin d'exister à l'instant de l'appel il sera créé la première fois que myVar est référencée, juste comme une variable ordinaire. Il ne doit pas exister une variable du nom de myVar à l'instant où upvar est appelée.
myVar est toujours traité comme le nom d'une variable, pas un élément de tableau. Même si le nom ressemble à un élément de tableau, tel que a(b), une variable ordinaire est créée. otherVar peut se référer à une variable scalaire, un tableau, ou un élément de tableau. upvar retourne une chaîne vide.
La commande upvar simplifie l'implémentation d'appel par nom des fonctions et facilite aussi la création de structures de contrôle en tant que fonctions Tcl. Par exemple, considérez les fonctions suivantes:
proc add2 name { upvar $name x set x [expr $x+2] }
add2 est appelée avec un argument donnant le nom d'une variable, et elle ajoute deux à la valeur de cette variable. Bien que add2 aurait pu être implémentée en utilisant uplevel au lieu de upvar, upvar simplifie l'accès aux variables de add2 dans le cadre de la fonction appelante.
namespace eval est une autre façon (en plus des appels de fonction) de changer le contexte de nom Tcl. Elle ajoute un cadre d'appel à la pile pour représenter le contexte namespace. Ceci signifie que chaque commande namespace eval compte comme un niveau d'appel supplémentaire pour les commandes uplevel et upvar. Par exemple, info level 1 renverra une liste décrivant une commande qui est soit l'appel de fonction le plus externe ou la commande namespace eval la plus externe. Également, uplevel #0 évalue un script au premier plan dans le namespace le plus externe (le namespace global).
Si une variable upvar est effacée (ex. x dans add2 plus haut), l'opération unset affecte la variable liée, pas la variable upvar. Il n'y a aucun moyen d'effacer une variable upvar excepté en sortant de la fonction dans lequel elle est définie. Néanmoins, il est possible de re-cibler une variable upvar par l'exécution d'une autre commande upvar.
upvar interagit avec les traces d'une manière directe mais qui peut être inattendue. Si une trace de variable est définie sur otherVar, cette trace sera déclenchée par les actions impliquant myVar. Néanmoins, à la fonction trace sera transmis le nom de myVar, plutôt que le nom de otherVar. Ainsi, la sortie du code suivant sera localVar plutôt que originalVar:
proc traceproc { name index op } { puts $name } proc setByUpvar { name value } { upvar $name localVar set localVar $value } set originalVar 1 trace variable originalVar w traceproc setByUpvar originalVar 2
Si otherVar se réfère à un élément de tableau, alors les traces de variables fixée pour le tableau entier ne seront pas appelées quand myVar est accédée (mais les traces sur un élément particulier pourront être appelées). En particulier, si le tableau est env, alors les changement faits à myVar ne seront pas transmis au sous-processus correctement