Ciascuna variabile ha una sua specifica area di visibilità: ciò significa che può essere valutata correttamente dall’interprete Tcl soltanto all’interno di questa sua area di visibilità.

In Tcl esistono diversi livelli di aree di visibilità.

Ora ne vediamo tre ordinati a partire da quello più ampio a quello più ristretto:

  1. Livello globale (global)
  2. Livello definito da una etichetta (namespaces)
  3. Livello singola procedura (proc)

Quando l’interprete esce dall’area di visibilità di una variabile, libera lo spazio di memoria occupato dalla variabile. Questo sistema automatico prende il nome di garbage-collection.

In questo articolo ci concentreremo soltanto sulle aree di visibilità dei livelli 1 e 3 visti in precedenza, rimandando ad un altro articolo la trattazione dei namespaces.

Area di visibilità globale e a livello di procedura

L’area di visibilità può essere definita o cambiata attraverso l’uso dei seguenti due comandi:

  • global
  • upvar

Con il comando global facciamo in modo che una variabile definita all’interno di una procedura diventi visibile anche all’esterno della procedura.

Con il comando upvar facciamo in modo che una variabile definita all’interno di una procedura diventi visibile anche all’interno di un’altra procedura: simulando quindi un passaggio per riferimento.

Vediamo la sintassi del comando upvar:

upvar ?level? otherVar1 myVar1 ?otherVar2 myVar2? …

Spiegazione: la variabile myVar1 diventa una referenza della variabile otherVar1 e myVar2 una referenza della variabile otherVar2. Alle variabili otherVar1 e otherVar2 viene inoltre assegnato un livello di area di visibilità relativo alla procedura corrente. Per esempio il livello 1 (che è anche il livello di default) corrisponde al livello subito superiore a quello della procedura.

Se al valore del livello si antepone il carattere #, allora il valore numerico farà riferimento ai livelli discendenti a partire dal livello globale che corrisponde al valore #0.

Due buoni consigli

Se possibile bisognerebbe sempre cercare di evitare di utilizzare le variabili globali che in progetti di una certa dimensione possono generare dei conflitti.

Questi conflitti sono superabili utilizzando la tecnica dei namespaces che, come detto, vedremo in un articolo dedicato.

Esempio con upvar

proc SetPositive {variable value } {
    upvar 1 $variable myvar
    if {$value < 0} {
        set myvar [expr {-$value}]
    } else {
        set myvar $value
    }
    return $myvar

    # Or more concisely:
    # set myvar [expr {abs($myvar)}]
}

SetPositive x 5
SetPositive y -5

puts "X : $x    Y: $y\n"
---
X : 5    Y: 5

Nel prossimo articolo vedremo la struttura dati della lista.