作用域
set alpha 1
proc myproc {} {
puts $alpha
}
myproc
此程式碼不起作用,因為兩個 alpha 位於不同的範圍內。
命令 set alpha 1
在全域性範圍內建立一個變數(使其成為全域性變數)。
命令 puts $alpha
在命令 myproc
執行時建立的範圍內執行。
這兩個範圍是截然不同的。這意味著當 puts $alpha
試圖查詢名稱 alpha
時,它找不到任何這樣的變數。
但是,我們可以解決這個問題:
proc myproc {} {
global alpha beta
puts $alpha
}
在這種情況下,兩個全域性變數 alpha
和 beta
在過程的範圍內連結到別名變數(具有相同的名稱)。從別名變數讀取將檢索全域性變數中的值,並且寫入它們會更改全域性變數中的值。
更一般地說,upvar
命令為來自任何先前作用域的變數建立別名。它可以與全域性範圍一起使用(#0
):
proc myproc {} {
upvar #0 alpha alpha beta b
puts $alpha
}
別名可以與連結到(alpha
)或其他名稱(beta
/ b
)的變數同名。
如果我們從全域性範圍呼叫 myproc
,這個變體也可以工作:
proc myproc {} {
upvar 1 alpha alpha beta b
puts $alpha
}
範圍編號 1
表示先前範圍或呼叫者範圍。
除非你真的知道你在做什麼,#0
,0
和 1
是與 upvar
一起使用的唯一有意義的範圍。 (upvar 0
為區域性變數建立一個本地別名,而不是嚴格的作用域操作。)
其他一些語言通過花括號定義範圍,讓每個範圍內執行的程式碼檢視周圍範圍內的所有名稱。在 Tcl 中,在呼叫過程時會建立一個單一的作用域,並且只有它自己的名稱可見。如果過程呼叫另一個過程,則其作用域將堆疊在前一個作用域的頂部,依此類推。這意味著與僅具有全域性範圍和區域性範圍(使用子範圍)的 C 風格語言相比,每個範圍充當它已開啟的任何範圍的封閉(但不是立即可見)範圍。過程返回時,其範圍將被銷燬。