不,不是。命名空間和調用框架是非常不同的概念。命名空間是可以消除同義詞歧義的名稱的層次結構。程序中可能有三個名爲foo
的變量,但如果將它們放在不同的名稱空間中,它們不會發生衝突。命名空間可以用於變量名和命令名。一旦使用namespace eval
創建,名稱空間的內容將始終可用,直到您致電namespace delete
。
調用堆棧是一系列堆棧幀。第一個堆棧幀#0始終存在。無論何時調用命令,都會創建其他堆棧框架(這主要適用於用戶定義過程的命令,「內置」命令遵循其自己的規則)。命令返回時,它們會再次被銷燬。所以,如果你命令A和A調用命令B和B調用命令C,你有一個調用堆棧看起來像這樣:
#3 : <C's variables>
#2 : <B's variables>
#1 : <A's variables>
#0 : <global and namespace variables>
每個堆棧幀是在意義上的範圍,只有變量在那裏創建或導入到它可以訪問,除非你使用upvar
。其他一切都是隱藏的。在大多數編程語言中,可以從內部作用域自動訪問外部作用域的名稱,例如全局作用域。在Tcl中不是這樣。
使用upvar
您可以讓命令查看自己堆棧框外的事情。 C可以使用upvar #0 foo bar
爲全局變量foo
創建別名(bar
),或者使用upvar 1 baz qux
(不帶#的註釋)爲B的堆棧幀中的變量baz
創建別名(qux
)。
uplevel
命令可以沿着相同的行使用在另一個棧幀中執行腳本,包括全局腳本。在執行期間,腳本可以訪問堆棧幀中的所有內容,但沒有其他內容,包括從中調用的堆棧幀中的變量。
C也可以使用upvar #0 ::abc::def ghi
爲名稱空間變量::abc::def
創建別名,但不要這樣做,請改用namespace upvar ::abc def ghi
。
而不是upvar #0 foo foo
你可以使用global foo
導入一個全局變量。在名稱空間中定義的命令內,variable
命令可以導入在同一名稱空間中定義的變量。
將#upvar
或uplevel
分爲#0(全局幀)或1(呼叫者的幀)通常是有用的。使用其他幀編號很容易出錯,通常表示設計不佳。調用upvar 0 foo bar
在同一個堆棧幀中爲變量(foo
)創建一個別名(bar
),這可能會非常有用。
由正在處理的事件調用的命令在調用堆棧外部使用全局級別執行。他們無法到達活動的堆棧幀並訪問駐留在其中的變量。
一個簡單的示範:
namespace eval ::abc {
variable def 42
proc xyz {} {
variable def
}
}
set foo 1138
proc A {} {
B
}
proc B {} {
set baz 1337
C
}
proc C {} {
upvar #0 foo bar
puts $bar
upvar 1 baz qux
puts $qux
namespace upvar ::abc def ghi
puts $ghi
}
只有一些命令推堆棧幀。每個人都知道的是程序調用和'命名空間評估'。 (還有其他幾個,特別是TclOO ...) – 2015-01-15 19:43:06
謝謝,@Hoodiecrow,你填寫了一些細節。很多使用Google的人向我透露,名稱空間與調用框架不同。而且這些命名空間是可選的,也許最好在小腳本中避免(但對代碼重用有用)。調用過程被調用時也會創建調用框架。進一步澄清:在我的問題中,我是否說過任何不真實的東西? – 2015-01-16 00:10:42
@ user901750:有一些有問題的陳述。你在說棧架有時被稱爲調用堆棧。這是錯誤的,但我認爲這是一個錯誤? 'proc'命令不會創建棧幀(但它創建的命令在被調用時會執行)。命名空間不會改變Tcl的命名上下文,但是'namespace eval'會(通過創建一個新的堆棧幀)。 'upvar'和'uplevel'不能用於(操作)名稱空間,但可以像處理變量的其他任何命令一樣訪問名稱空間變量。 – 2015-01-16 08:50:56