====== upvar ======
Crée un lien vers une variable dans un cadre de pile différent
===== Syntaxe =====
upvar ?level? otherVar myVar ?otherVar myVar...?
===== Description =====
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 [[:tcl: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.
[[:tcl:namespace#eval|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 [[:tcl: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**.
==== Traces et 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 [[:faq:env]], alors les changement faits à //myVar// ne seront pas transmis au sous-processus correctement
===== Exemples =====
===== Voir aussi =====
{{tag>tcl}}