Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/react-native/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Variables 确定Tcl中变量的类型_Variables_Tcl_Object Type - Fatal编程技术网

Variables 确定Tcl中变量的类型

Variables 确定Tcl中变量的类型,variables,tcl,object-type,Variables,Tcl,Object Type,我正在寻找一种在Tcl中查找变量类型的方法。例如,如果我有一个变量$a,我想知道它是否是一个整数 到目前为止,我一直在使用以下工具: if {[string is boolean $a]} { #do something } 这似乎对以下类型非常有效: alnum、alpha、ascii、boolean、control、digit、double、false、graph、integer、lower、print、putch、space、true、upper、wordchar

我正在寻找一种在Tcl中查找变量类型的方法。例如,如果我有一个变量$a,我想知道它是否是一个整数

到目前为止,我一直在使用以下工具:

    if {[string is boolean $a]} {
    #do something
    }
这似乎对以下类型非常有效:
alnum、alpha、ascii、boolean、control、digit、double、false、graph、integer、lower、print、putch、space、true、upper、wordchar、xdigit


但是,它不能告诉我我的变量是数组、列表还是字典。有人知道一种方法来判断一个变量是否是这三个变量中的一个吗?

对于您想要的数组
数组存在
对于您想要的dict
dict存在

对于一个列表,我不认为在8.5?之前有一个内置的方式,这是从


Tcl的变量没有类型(除了它们是否真的是变量的关联数组-即使用
$foo(bar)
语法-您使用
数组存在
),但Tcl的值有。嗯,有点。Tcl可以根据需要在不同类型之间改变值,并且不公开此信息[*];您真正能做的就是检查值是否符合特定类型

此类一致性检查是使用
字符串is
(出于历史原因,您需要
-strict
选项):

请注意,所有值都符合字符串的类型;Tcl的值总是可序列化的

[EDIT from comments]:对于JSON序列化,可以使用肮脏的黑客来使用Tcl 8.6生成“正确”的序列化(严格地说,从Tcl的角度来看,将所有内容放在一个字符串中是正确的,但这对其他语言没有帮助)。最初发布在上的执行此操作的代码是:

警告:不支持上述代码。这取决于肮脏的黑客。它很容易在没有警告的情况下坏掉。(但它确实有效。移植到Tcl 8.5需要一个小小的C扩展来读取类型注释。)



[*]严格地说,它确实提供了一个不受支持的接口,用于发现8.6中某个值的当前类型注释(作为
::tcl::unsupported::representation
)的一部分),但该信息是故意以人类可读的形式出现的,可能会在不经宣布的情况下进行更改。这是为了调试,而不是代码。此外,Tcl在内部使用了很多不同的类型(例如,缓存的命令和变量名),在正常情况下您不希望对这些类型进行探测;要确定一个变量是否是一个数组,事情是相当复杂的…

proc is_array {var} {
    upvar 1 $var value
    if {[catch {array names $value} errmsg]} { return 1 } 
    return 0
}   

# How to use it
array set ar {}
set x {1 2 3}
puts "ar is array? [is_array ar]"; # ar is array? 1
puts "x is array? [is_array x]";   # x is array? 0

如果您想处理JSON,那么我强烈建议您阅读Tcl wiki上的JSON页面:


在那个页面上,我发布了一个简单的函数,该函数在给定格式描述符的情况下将Tcl值编译为JSON字符串。我还发现该页面上的讨论内容非常丰富。

其他答案都提供了非常有用的信息,但值得注意的是,许多人一开始似乎并不喜欢这些信息

在Tcl中,值没有类型。。。他们的问题是它们是否可以用作给定的类型。你可以这样想

string is integer $a
你不是在问

美元中的值是整数吗

你问的是

我可以使用$a中的值作为整数吗


当你沿着“这是一个整数”的思路思考这两个问题的区别时,它是有用的。每个整数也是(一个元素的)有效列表。。。因此它可以用作,并且两个字符串都是命令将返回true(对于整数,其他几个命令也会返回true)。

对于判断值是否可用作字典的特定情况,tcllib有一个
dict is_dict
命令,如果
可以作为一个值,它将返回一个真值。

谢谢:)您能解释一下在这种情况下如何使用dict吗?我尝试过这样使用它:如果{[dict exists$testData2 nullval]}{#do something},但如果变量不是dict,它将返回错误@Tom,在这种情况下,我会将if语句包装为“catch”,这将允许您处理变量不是dict的情况。谢谢您的反馈,但这似乎行不通。在if{[string is list$foo]}{部分。包含多个单词的字符串也可以看到als列表。此外,如果我的列表包含偶数项,则此代码将始终将其分类为字典。我不确定我尝试执行的操作是否可行,但您的代码也可能是最好的解决方案。@Tom,这是因为包含mul的字符串tiple words与使用“list”命令创建的变量没有区别。例如,尝试以下操作:set foo“ab bb dd”;lindex$foo 1is
string是list
8.5或8.6?,据我所知,Tom可能无法使用它?它在8.5中,这是当前的标准生产级别版本。在8.4上(或之前!)将使您有资格成为“过时的”(或被困在Java中)。@Tom:嗯,所有偶数长度的列表都是有效的字典,尽管可能表示形式不太理想(例如,重复键)。你需要它的什么版本?你能解释一下为什么你首先需要它吗?我的意思是,既然TCL本质上是一种无类型语言,你所要求的看起来像是在自找麻烦。@Kostix,当然不是。我需要它的原因是创建一个过程,在这个过程中,字典被解析为JSON。例如,JSON中的字符串是surroun由“”编码,而整数不是。另外,如果字典要包含另一个字典,该字典应该在JSON对象中获得自己的JSON对象。@Tom,我会选择另一种方法,并要求包的用户向序列化程序提供一个(人工的)使用显式类型标记的带注释的结构。如
序列化[object$mykey1[int$value]$mykey2[float$bar]]
等。尝试推断无类型值的类型是错误的
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\""
}
proc is_array {var} {
    upvar 1 $var value
    if {[catch {array names $value} errmsg]} { return 1 } 
    return 0
}   

# How to use it
array set ar {}
set x {1 2 3}
puts "ar is array? [is_array ar]"; # ar is array? 1
puts "x is array? [is_array x]";   # x is array? 0
string is integer $a