在 Tcl 中检查参数是否为字典

Check if an argument is a dictionary or not in Tcl

我想要一个 proc,如果它的参数是否是 Tcl 8.5 及更高版本的字典,它就会执行某些操作。 我无法从 Tcl dict 命令中找到任何直接的东西。 我可以使用的代码是:

proc dict? {dicty} { 
    expr { [catch { dict info $dicty } ] ? 0 : 1 }
}

有什么w/o使用catch,内置的东西吗?
谢谢。

您的方法存在缺陷,因为 Tcl 具有动态类型系统,其中值的实际类型能够动态变形并取决于应用到它的命令—观察:

$ tclsh
% info pa
8.5.11
% dict info {a b}
1 entries in table, 4 buckets
number of buckets with 0 entries: 3
number of buckets with 1 entries: 1
number of buckets with 2 entries: 0
number of buckets with 3 entries: 0
number of buckets with 4 entries: 0
number of buckets with 5 entries: 0
number of buckets with 6 entries: 0
number of buckets with 7 entries: 0
number of buckets with 8 entries: 0
number of buckets with 9 entries: 0
number of buckets with 10 or more entries: 0
average search distance for entry: 1.0
% llength {a b}
2
% string len {a b}
3
% 

如您所见,相同的值 {a b} 是一个字典、一个列表和一个字符串:在每种情况下,该值在 Tcl 命令期望的那一刻获得其 "real" 类型特定类型的值将值的 "default" 类型(字符串)转换为命令操作的类型。

你现在应该明白尝试调用 dict? {a b} 没有什么意义,因为值 {a b} 是一个完美的字典,也是一个完美的列表和一个完美的字符串,并且如果当前解释器中有自定义命令处理元组(固定长度的列表),那么它可能是一个完美的元组。

因此,您应该采取的真正方法是对传递给您希望包含字典的命令的那些值盲目地使用 dict 命令。如果用户将设法向您的命令传递一些不可解释为字典的内容,则 dict 命令将失败,这是一件好事,因为这样的错误实际上无法恢复(这是一个编程错误) .

任何依赖于值的特定类型的尝试都将再次成为 Tcl 的 implicit/dynamic 类型的核心思想。对于 Tcl C API.

甚至是这样

如果你真的想问如何确定当前的 Tcl 版本 支持 dict 命令,而不是关于特定值的类型,请测试 Tcl 的在启动时的某处版本并将其保存为标志,如下所示:

set hasDicts [expr {[package vcompare [info tclversion] 8.5] >= 0}]

但请注意,依赖于 hasDicts 值的代码现在处于某个灰色区域,因为如果用户未向您提供您使用 dict 命令处理的值,那么您使用什么命令来处理它们?

另请注意,dict 命令可以以可加载模块的形式添加到 Tcl 8.4 解释器中(参见 this)。

您可以通过查看值是否为列表以及它是否具有偶数个元素来测试值是否为字典; 所有甚至长度的列表都可以用作字典(尽管由于重复键等原因,许多自然不是规范字典)。

proc is-dict {value} {
    return [expr {[string is list $value] && ([llength $value]&1) == 0}]
}

您可以使用 tcl::unsupported::representation 查看 Tcl 8.6 中的实际类型,但 不建议 因为像文字这样的东西是即时转换为字典。以下是合法的,显示了您可以做什么,并显示了限制(

% set value {b c d e}
b c d e
% tcl::unsupported::representation $value
value is a pure string with a refcount of 4, object pointer at 0x1010072e0, string representation "b c d e"
% dict size $value
2
% tcl::unsupported::representation $value
value is a dict with a refcount of 4, object pointer at 0x1010072e0, internal representation 0x10180fd10:0x0, string representation "b c d e"
% dict set value f g;tcl::unsupported::representation $value
value is a dict with a refcount of 2, object pointer at 0x1008f00c0, internal representation 0x10101eb10:0x0, no string representation
% string length $value
11
% tcl::unsupported::representation $value
value is a string with a refcount of 2, object pointer at 0x1008f00c0, internal representation 0x100901890:0x0, string representation "b c d e f g"
% dict size $value;tcl::unsupported::representation $value
value is a dict with a refcount of 2, object pointer at 0x1008f00c0, internal representation 0x1008c7510:0x0, string representation "b c d e f g"

如您所见,Tcl 中的类型(按设计)有点不稳定,因此强烈建议您根本不要依赖它们。