2012-12-26 178 views
1

我有幾個函數在我導出的命名空間「b」中定義。然後我進口這些功能來命名空間:: X :: Y,正是如此:tcl命名空間錯誤

namespace eval ::x::y "namespace import fun" 

一段時間後,我做的:

namespace eval ::x::y fun 

哪裏好玩呢:

proc fun {} { 
    puts "[namespace current]" 
    uplevel {puts "[namespace current]"} 
} 

什麼是印刷是:

 
::b 
::x::y 

我想和需要的是'有趣'發生在:: x :: y而不是:: b中。我究竟做錯了什麼?

+2

將過程名稱從一個名稱空間導入到另一個名稱空間不會更改定義該過程的名稱空間,因此在調用該過程時不會更改當前名稱空間。也許你可以分享更多的問題,並且會出現其他一些想法。 –

+0

如果你正在嘗試做一個窮人的面向對象,**停下來!**使用其中一個_real_面向對象系統(或8.6.0,其中有一個烘焙)來解決這個問題。 –

回答

1

這不是Tcl的命名空間的工作方式。每個過程只與一個名稱空間相關聯,該名稱空間就是其名稱所在的名稱空間。當您使用namespace import時,該過程的別名放置在導入名稱空間中,該名稱空間允許從該其他名稱空間調用該過程,但該過程本身保留在其原始名稱空間中並在該名稱空間中執行。

如果你想知道調用者的命名空間,使用uplevel namespace current(或uplevel 1 {namespace current}稍微更小但更有效的版本)。這實際上並不告訴你哪個命名空間包含了用來調用該過程的命令;對於這一點,你需要這個怪物(在調用的命令):

namespace qualifiers [uplevel 1 [list namespace which [lindex [info level 0] 0]]] 

當然,如果你需要的是大量的,那麼你很可能做錯了什麼。 (很明顯,考慮到獲取信息所需的代碼的長度和複雜性)。

特別是,如果你假裝用這種方法做對象定向,請停止並使用一個真正的對象系統來獲取所有棘手的問題細節正確。 Tcl 8.6.0包含onetwo,如果您有提供的擴展名),並且有許多可用作擴展包的舊版本。

+0

其實@Donal,我試圖與幾個名稱空間共享代碼,並且默認情況下,它們具有相同的例程訪問權限,這些變量在不同的名稱空間中。在我正在研究的情況下,我實現了頁面,每個頁面都有一個窗口和一個可以使用的大量函數。最後,我只是將這些功能包含在每個名稱空間中。該應用程序用於具有命名行和列的tcl/tk電子表格程序。它的早期版本在sourceforge上是tk#。 –

+0

@Tom真的,這聽起來(首先猜測),就像你重新發明了面向對象。我忘記了已經完成的時間(我已經完成了3-4次!)請不要再做。有一些非常好的生產系統(Itcl,XOTcl,TclOO)處理困難的邊緣案例。節省自己很多工作! –

+0

呵呵,TclOO是封面下的命名空間。再加上一些聰明的調度代碼... –