Tcl:单元素列表

Tcl: single-element lists

我有两个关于 Tcl 在单元素列表上的行为的问题。如 and discussed in https://wiki.tcl-lang.org/page/list(“单字列表与非列表值”部分)所述,单个元素周围的大括号(大括号)被删除。

我正在编写一个存在问题的应用程序,所以我想知道如何防止这种行为并为单元素列表保留大括号。

我的第一个问题是:在 Tcl 解释器中,这个大括号移除发生在什么地方?这些是特定命令,还是发生在解释器的更深处?

list 似乎是一个删除大括号的命令:

% list a b
a b
% list a {b}
a b
% list a {{b}}
a {{b}}

但在 puts 中不会发生:

% puts "a b"
a b
% puts "a {b}"
a {b}
% puts "a {{b}}"
a {{b}}

实际上,我认为 list 中的行为非常不一致:

% set l {a {b}}
a {b}
% set l [list a [list b]]
a b

我的第二个问题是:我怎样才能防止这种牙套移除?

感谢您的帮助!

大括号是列表中的引用机制和一般的 Tcl 解释器。列表格式化引擎优先避免所有引用,否则如果必须引用并且可以这样做,则使用大括号,如果没有其他方法,将退回到反斜杠。它从不选择使用双引号;理论上我们可以在未来改变它,但在实践中这是极不可能的。

在这种情况下:

list a {b}

b 周围的大括号是 Tcl 脚本引号list 命令根本看不到它们。当我们列出一个列表时:

list a {{b}}

我们现在有了第二个元素,它的值中有大括号;我们可以从中看到:

set theValue [ list a {{b}} ]
puts [lindex $theValue 1]

在这种情况下:

puts "a {b}"

你在做一些不同的事情:你在事物周围加上双引号。该值也是一个列表,尽管不是规范形式的列表:

set theValue "a {b}"
puts [lindex $theValue 1]

非规范列表的 space 相当大,但通常不建议您在更改时详细探索它(除了将一种类型的白色 space 分隔符更改为另一种,例如单 space 到换行符和缩进以在源代码中创建一个更好看的文字列表)有点难以正确。如果您从非常量位构建列表,请使用标准命令来执行此操作,因为它们可以正确处理所有棘手的边缘情况。 (非规范列表是那些解析为列表但你永远无法摆脱 list 命令及其朋友如 lrangelappend 的列表。)


如果您尝试呈现列表并且默认的规范表示法不够用,请试试这个(假设您有 Tcl 8.6):

puts [string cat "\{" [join $theListToRender "\} \{"] "\}"]

这会将 a b 的输入列表更改为 {a} {b}。除了最可怕的情况(主要是那些不平衡的大括号;那是 Tcl 的内置列表引用切换到产生大量丑陋的反斜杠的情况),它会产生非规范但有效的列表。您似乎想要的另一种形式不是 Tcl 默认情况下知道如何生成的东西:一个参数被支撑而另一个没有被支撑的事实在它到达渲染器时已经主动消失。 (您的示例中的文字 b{b} 实际上最终成为相同的字节码,包括相同的文字值。)