我在理解以下命令时遇到一些问题:
package ifneeded HelloWorld 1.0 [list source [file join $dir helloworld.tcl]]
pkgIndex.tcl中的, 据我所知,当pkgIndex.tcl来源时,我们打包需要HelloWorld 1.0,helloworld.tcl将被采购。我不明白列表命令......
答案 0 :(得分:7)
package ifneeded
命令用于注册(或查询)如何使包实际出现在Tcl解释器中。这是通过评估脚本来完成的,该脚本是在您的示例中使用list
生成的参数。让我们解构它。
package ifneeded HelloWorld 1.0 [list source [file join $dir helloworld.tcl]] ---------------- ========== --- ============================================= command name package ver how to make it present, name result of [list ...]
到目前为止,这么好。现在,暂时不说:list
命令不只是用于制作列表,而且还使保证替换免费命令。也就是说,它的结果是一个脚本,它包含一个命令及其参数的调用,就像它们进入list
命令时一样。
这意味着我们正在制作一个source somefilename
的脚本,其中somefilename
是file join
的结果。换句话说,你得到几乎同样的事情:
package ifneeded HelloWorld 1.0 "source $dir/helloworld.tcl"
除之外,没有假设文件名分隔符是/
(这正是操作系统的一个特性,不是Tcl的特征,而file join
知道差异) 和如果$dir
碰巧包含空格或其他元字符(比您希望的更常见),则是安全的。
什么是$dir
?好吧,它是pkgIndex.tcl
脚本的一个特殊功能,它们(通常)在一个上下文中进行评估,该上下文将dir
变量设置为包含pkgIndex.tcl
脚本的目录的绝对名称。 (此时您不能对当前目录做出假设;它属于主Tcl程序的用户,而不属于包作者。)这使得重新定位包非常容易,因为您可以放置其所有组件相对于一个脚本的文件,只需将整个批次移动到一个块中。
答案 1 :(得分:1)
包ifneeded 命令expects以下输入:
package ifneeded package version ?script?
您可以看到,在您的情况下,包是HelloWorld,版本是1.0。最后,脚本是[list source [file join $ dir helloworld.tcl]]。使用 list 的原因是script参数需要列表。
答案 2 :(得分:1)
package ifneeded
命令期望脚本作为其最后一个参数。期望(通常意义上)脚本格式良好,即可由Tcl解析器解析。
在这个标准pkgIndex.tcl
的情况下,需要确保的是:无论处理pkgIndex.tcl
的代码时“dir”变量包含什么,脚本都应该是以这种方式构造,以后Tcl解析器在其中看到source
命令,其中只有一个参数 - 无论$dir
是否扩展为包含空格或时髦字符如{ {1}}等等。
输入{
命令。这里,它用于构造两个元素的列表:字符串“source”和包含文件名的字符串(用作该list
命令的唯一参数)。现在,当该列表被解释为脚本(字符串)时,Tcl确保字符串表示包含所有必需的引用以消除关于空格等的任何歧义。
这确保了解析器稍后解释我们构造的脚本时,其中的source
命令将只接收一个参数。
您可以阅读更多有关使用source
来防止引用问题的更好的书面信息here。