欢迎光临散文网 会员登陆 & 注册

2022年的 Tcl 编程语言入门参考 3.作用域&命名空间

2022-04-09 18:29 作者:象喻  | 我要投稿

global、upvar、uplevel、namespace、variable

作用域

作用域 = 起作用的区域

🤪初学编程请注意:用简单的字,创造出所有人都不懂的词汇,是计算机行业的必备技能(中外都一样);把本不复杂的概念,人为创造条件,让它复杂化,是计算机行业自古以来不懈的追求!

代码越长创建的变量就越多,为了解决重名冲突、误操作问题,就引入了作用区域限制(即作用域)。最常见的就是每个自定义命令里的变量跟其它变量不会发生冲突。

作用域的规则在不同的编程语言中并不一样,Tcl/Tk的作用域规则跟文件系统很像:

把tcl源代码想象成📁主文件夹;把自定义命令想象成📂子文件夹;把变量想象成文件夹里的📄文件。

在自定义命令里创建的变量,就像在子文件夹中的文件一样,即便同名也互不影响:


global

想要使用源代码中的变量(就是在自定义命令之外的),简单的方法是使用global命令,注意无论在任何位置调用global命令,使用的都是最顶层的变量。

上例中自定义命令与内嵌匿名命令按层级排号的话(后面upvar和uplevel命令会用到):

set a 111 位于最顶层,在Tcl语言中用第 #0 层表示

proc 套个匿娃…… 的代码段,就低了一层,用 #1 表示

apply 代码段,比 套个匿娃 还低一层,用 #2 表示(匿名命令也是自定义命令,相当于套个匿娃的子命令)

以此类推……如果再继续嵌套的话,就继续往后排。

⚠️编程中有个术语叫"全局变量",表示全范围可以使用的变量,但是各个语言的具体定义不同。Tcl语言把 #0 层的变量叫全局变量,这个定义跟现在流行语言的差异有点大,所以在此特意规避了"全局变量"这个词,以免对其他程序员造成:击晕、迷惑、混乱、强迫脱发伤害。


参数传递

想要灵活使用变量,有一种繁琐但简单的方法:给自定义命令添加参数,把变量传递给命令。这个方法的好处是逻辑简单,缺点是代码量大,且容易出错。

该方法适合变量比较少的情况。

此外,想要以很少的代码灵活使用变量,需要借助upvar命令。如果顺便掌握uplevel命令,还可以在其它层级运行语句。

⚠️友情提醒:执着于两个命令的复杂用法(尤其是uplevel)将显著降低代码可读性和发密度。


upvar

该命令把其它层级的变量以别名的形式引入当前层级:

upvar  可选的层级参数  变量名  变量别名

可省略的层级参数:默认是1,表示向上一层;2表示向上两层,以此类推。也可以用前面介绍的层级标号#0、#1、#2……

变量别名是变量的另一个名字,即同一个变量有了两个名字。

从例子中也能看出upvar的层级参数确实很少用:如果使用#0变量,global更直观不易出错。而绝大多数情况下,也就到#2层了。😍当然如果阁下习惯把文件放在18层子目录里……那也没必要把这个习惯带入到编程中(删库代码除外)


uplevel

uplevel命令在指定的层级上执行代码,也就是说,uplevel的代码段是在其它层级上运行的。

uplevel 可选的层级参数 代码段

代码段:uplevel命令会把层级参数后面的参数自动拼接成代码。但是在没有替换需求时,推荐用{}括起来,除了更直观外,还可以提高执行效率,省略拼接字符串的过程


命名空间

对于一份源代码来说呢,有作用域就足够了。但程序经常是由好多源代码文件组成的。就不可避免地出现重名问题,别说变量了,就是连自定义命令重名儿的都很多。为了解决这个问题,就引入了命名空间这个概念。

命名空间,就相当于姓氏;变量跟自定义命令,就相当于名字。有名有姓,就不会重复了。

坑爹的缺陷

按惯性思维,命名空间内的变量都应该属于该空间,然而并非如此。命名空间跟proc自定义命令不同,它不是#1层,它仍然是#0层。所以命名空间内的变量必须用variable命令声明,才能够算该空间内的变量(也就是宣告变量属于该命名空间)

*这里只介绍命名空间概念,更多内容请参考官方文档。命名空间的实用例子可以查看Tcl语言lib文件夹里的扩展库(找纯.tcl文件的扩展库,别找dll的)。当你用到命名空间了,你就是成熟的码农了,作为一个成熟的……


2022年的 Tcl 编程语言入门参考 3.作用域&命名空间的评论 (共 条)

分享到微博请遵守国家法律