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

时间:2015-03-17 11:50:38

标签: dictionary tcl catch-block

我希望有一个proc,如果它的'参数是Tcl 8.5及以上的字典,它会做什么。 我从Tcl dict命令中找不到任何直截了当的东西。 我可以使用的代码是:

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

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

2 个答案:

答案 0 :(得分:5)

您可以通过查看值是否为列表以及是否具有偶数个元素来测试值是否为字典; 所有甚至长度列表都可以用作词典(尽管很多都不是规范词典,因为重复键之类的东西)。

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中的类型有点滑(按设计),因此强烈建议您完全不依赖它们。

答案 1 :(得分: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命令将失败,并且这样做是件好事,因为这样的错误实际上无法恢复(&#&# 39;编程错误)。

任何依赖于值的特定类型的尝试都会再次成为Tcl隐式/动态类型的概念。对于Tcl C API来说,情况确实如此。


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

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

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

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