2022年的 Tcl 編程語言入門參考 3.作用域&命名空間
作用域 = 起作用的區(qū)域
??初學編程請注意:用簡單的字,創(chuàng)造出所有人都不懂的詞匯,是計算機行業(yè)的必備技能(中外都一樣);把本不復雜的概念,人為創(chuàng)造條件,讓它復雜化,是計算機行業(yè)自古以來不懈的追求!
代碼越長創(chuàng)建的變量就越多,為了解決重名沖突、誤操作問題,就引入了作用區(qū)域限制(即作用域)。最常見的就是每個自定義命令里的變量跟其它變量不會發(fā)生沖突。
作用域的規(guī)則在不同的編程語言中并不一樣,Tcl/Tk的作用域規(guī)則跟文件系統(tǒng)很像:
把tcl源代碼想象成??主文件夾;把自定義命令想象成??子文件夾;把變量想象成文件夾里的??文件。
在自定義命令里創(chuàng)建的變量,就像在子文件夾中的文件一樣,即便同名也互不影響:
global
想要使用源代碼中的變量(就是在自定義命令之外的),簡單的方法是使用global命令,注意無論在任何位置調(diào)用global命令,使用的都是最頂層的變量。
上例中自定義命令與內(nèi)嵌匿名命令按層級排號的話(后面upvar和uplevel命令會用到):
set a 111 位于最頂層,在Tcl語言中用第 #0 層表示
proc 套個匿娃…… 的代碼段,就低了一層,用 #1 表示
apply 代碼段,比 套個匿娃 還低一層,用 #2 表示(匿名命令也是自定義命令,相當于套個匿娃的子命令)
以此類推……如果再繼續(xù)嵌套的話,就繼續(xù)往后排。
??編程中有個術(shù)語叫"全局變量",表示全范圍可以使用的變量,但是各個語言的具體定義不同。Tcl語言把 #0 層的變量叫全局變量,這個定義跟現(xiàn)在流行語言的差異有點大,所以在此特意規(guī)避了"全局變量"這個詞,以免對其他程序員造成:擊暈、迷惑、混亂、強迫脫發(fā)傷害。
參數(shù)傳遞
想要靈活使用變量,有一種繁瑣但簡單的方法:給自定義命令添加參數(shù),把變量傳遞給命令。這個方法的好處是邏輯簡單,缺點是代碼量大,且容易出錯。
該方法適合變量比較少的情況。
此外,想要以很少的代碼靈活使用變量,需要借助upvar命令。如果順便掌握uplevel命令,還可以在其它層級運行語句。
??友情提醒:執(zhí)著于兩個命令的復雜用法(尤其是uplevel)將顯著降低代碼可讀性和發(fā)密度。
upvar
該命令把其它層級的變量以別名的形式引入當前層級:
upvar ?可選的層級參數(shù) ?變量名 ?變量別名
可省略的層級參數(shù):默認是1,表示向上一層;2表示向上兩層,以此類推。也可以用前面介紹的層級標號#0、#1、#2……
變量別名是變量的另一個名字,即同一個變量有了兩個名字。
從例子中也能看出upvar的層級參數(shù)確實很少用:如果使用#0變量,global更直觀不易出錯。而絕大多數(shù)情況下,也就到#2層了。??當然如果閣下習慣把文件放在18層子目錄里……那也沒必要把這個習慣帶入到編程中(刪庫代碼除外)
uplevel
uplevel命令在指定的層級上執(zhí)行代碼,也就是說,uplevel的代碼段是在其它層級上運行的。
uplevel 可選的層級參數(shù) 代碼段
代碼段:uplevel命令會把層級參數(shù)后面的參數(shù)自動拼接成代碼。但是在沒有替換需求時,推薦用{}括起來,除了更直觀外,還可以提高執(zhí)行效率,省略拼接字符串的過程
命名空間
對于一份源代碼來說呢,有作用域就足夠了。但程序經(jīng)常是由好多源代碼文件組成的。就不可避免地出現(xiàn)重名問題,別說變量了,就是連自定義命令重名兒的都很多。為了解決這個問題,就引入了命名空間這個概念。
命名空間,就相當于姓氏;變量跟自定義命令,就相當于名字。有名有姓,就不會重復了。
坑爹的缺陷
按慣性思維,命名空間內(nèi)的變量都應(yīng)該屬于該空間,然而并非如此。命名空間跟proc自定義命令不同,它不是#1層,它仍然是#0層。所以命名空間內(nèi)的變量必須用variable命令聲明,才能夠算該空間內(nèi)的變量(也就是宣告變量屬于該命名空間)
*這里只介紹命名空間概念,更多內(nèi)容請參考官方文檔。命名空間的實用例子可以查看Tcl語言lib文件夾里的擴展庫(找純.tcl文件的擴展庫,別找dll的)。當你用到命名空間了,你就是成熟的碼農(nóng)了,作為一個成熟的……