Tom*_*Tom 10 variables tcl object-type
我正在寻找一种在Tcl中找到变量类型的方法.例如,如果我有变量$ a,我想知道它是否是一个整数.
到目前为止我一直在使用以下内容:
if {[string is boolean $a]} {
#do something
}
Run Code Online (Sandbox Code Playgroud)
这似乎适用于以下类型:
alnum,alpha,ascii,boolean,control,digit,double,false,graph,integer,lower,print,punct,space,true,upper,wordchar,xdigit
但是它无法告诉我我的变量是否可能是数组,列表或字典.有谁知道如何判断一个变量是否是这三个中的任何一个?
Don*_*ows 12
Tcl的变量没有类型(除了它们是否真的是一个变量的关联数组 - 也就是说,使用$foo(bar)
你使用的语法array exists
),但Tcl的值是这样的.嗯,有点.Tcl可以在它认为合适时改变不同类型之间的值,并且不会暴露这些信息[*]; 你所能做的就是检查一个值是否符合特定类型.
这样的一致性检查是完成的string is
(-strict
出于丑陋的历史原因,您需要选项):
if {[string is integer -strict $foo]} {
puts "$foo is an integer!"
}
if {[string is list $foo]} { # Only [string is] where -strict has no effect
puts "$foo is a list! (length: [llength $foo])"
if {[llength $foo]&1 == 0} {
# All dictionaries conform to lists with even length
puts "$foo is a dictionary! (entries: [dict size $foo])"
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,所有值都符合字符串的类型; Tcl的值始终可序列化.
[来自评论的编辑]:对于JSON序列化,可以使用脏黑客来产生"正确的"序列化(严格地说,从Tcl的角度来看,所有字符串都是正确的,但这对其他语言来说并不是很有用).最初在Rosetta Code上发布的代码是:
package require Tcl 8.6
proc tcl2json value {
# Guess the type of the value; deep *UNSUPPORTED* magic!
regexp {^value is a (.*?) with a refcount} \
[::tcl::unsupported::representation $value] -> type
switch $type {
string {
# Skip to the mapping code at the bottom
}
dict {
set result "{"
set pfx ""
dict for {k v} $value {
append result $pfx [tcl2json $k] ": " [tcl2json $v]
set pfx ", "
}
return [append result "}"]
}
list {
set result "\["
set pfx ""
foreach v $value {
append result $pfx [tcl2json $v]
set pfx ", "
}
return [append result "\]"]
}
int - double {
return [expr {$value}]
}
booleanString {
return [expr {$value ? "true" : "false"}]
}
default {
# Some other type; do some guessing...
if {$value eq "null"} {
# Tcl has *no* null value at all; empty strings are semantically
# different and absent variables aren't values. So cheat!
return $value
} elseif {[string is integer -strict $value]} {
return [expr {$value}]
} elseif {[string is double -strict $value]} {
return [expr {$value}]
} elseif {[string is boolean -strict $value]} {
return [expr {$value ? "true" : "false"}]
}
}
}
# For simplicity, all "bad" characters are mapped to \u... substitutions
set mapped [subst -novariables [regsub -all {[][\u0000-\u001f\\""]} \
$value {[format "\\\\u%04x" [scan {& } %c]]}]]
return "\"$mapped\""
}
Run Code Online (Sandbox Code Playgroud)
警告:不支持上述代码.这取决于肮脏的黑客行为.它可能会在没有警告的情况下破裂.(但它确实有效.移植到Tcl 8.5将需要一个微小的C扩展来读出类型注释.)
[*]严格来说,它确实提供了一个不受支持的接口,用于发现8.6中值的当前类型注释 - 作为其中的一部分::tcl::unsupported::representation
- 但该信息是故意以人类可读的形式,并且可能会在没有通知的情况下进行更改.它用于调试,而不是代码.此外,Tcl在内部使用相当多的不同类型(例如,缓存的命令和变量名称),在正常情况下您不希望进行探测; 引擎盖下的事情相当复杂......
其他答案都提供了非常有用的信息,但是值得注意的是,很多人一开始似乎并不讨厌。
在Tcl中,值没有类型...它们的问题是它们是否可以用作给定类型。你可以这样想
string is integer $a
Run Code Online (Sandbox Code Playgroud)
你不是问
$ a中的值是整数吗?
你要问的是
我可以将$ a中的值用作整数吗
考虑“这是整数”的思路时,考虑两个问题之间的区别是很有用的。每个整数也是(一个元素的)有效列表……因此can be used
,任何string is
一个都是整数,两个命令都将返回true(一个整数将返回其他几个命令)。
对于你想要的数组array exists
对于你想要的字典dict exists
对于列表,我认为 8.5 之前没有内置方式?,来自http://wiki.tcl.tk/440
proc isalist {string} {
return [expr {0 == [catch {llength $string}]}]
}
Run Code Online (Sandbox Code Playgroud)