1

我想要一个 proc,如果它的参数是 Tcl 8.5 及以上的字典,它会做一些事情。我从 Tcl dict 命令中找不到任何直接的东西。我可以工作的代码是:

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

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

4

2 回答 2

5

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

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

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

% 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 中的类型(按设计)有点棘手,因此强烈建议您根本不要依赖它们。

于 2015-03-17T14:08:14.477 回答
3

您的方法是有缺陷的,因为 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 命令转换“默认”类型该值是字符串,是命令操作的值。

您现在应该明白,尝试拨打电话dict? {a b}没有什么意义,因为该值{a b}是一个完美的字典,一个完美的列表以及一个完美的字符串,如果有自定义命令,它可能是一个完美的元组当前处理元组的解释器(固定长度的列表)。

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

任何依赖值的特定类型的尝试都再次成为 Tcl 的隐式/动态类型的想法。甚至 Tcl C API 也是如此。


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

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

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

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

于 2015-03-17T12:26:05.960 回答