如何检测该参数是两个任意类型的元组? [英] How to detect that parameter is a tuple of two arbitrary types?

查看:120
本文介绍了如何检测该参数是两个任意类型的元组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我实际上做的是更复杂,但是归结到能够实现函数来检测某个元素是一个元组,而不管它的元素是什么类型。



这是我的Approch不工作(见最后一行的注释):

  func isTuple任何) - > bool {
return b is(Any,Any)
}

let myString =aa
let myDouble = 1.2
isTuple myDouble))//返回false

为什么它不工作? Shouln't 任何在元组中也充当通配符?它是一个已知的Swift bug(如果不应该我认为它一个和报告)?是否有其他方法如何使 isTupple 方法工作?






EDIT



@ NateCook的回答完全回答了原始问题,但是不帮助我做我想做的事情。这是它:



我不仅需要确定某个东西是一个元组,而且还需要将它分成2个值,而不知道这些值的确切类型。 p>

这里是代码:

  func processIfTuple(b:Any){
if(b).disposition == MirrorDisposition.Tuple {
let(first,second)= b as(Any,Any)//转换时出错
process(first)
过程(第二)
}
}

func过程(值:任何){
...
}
$ b b processIfTuple((aa,1.2))

b是(Any,Any)不工作。这次尝试投射时出现错误。这可以解决吗?如果不是应该被认为是语言错误或缺少功能并报告?这肯定会导致大量的代码重复,因为我需要测试一个元组的所有可能的类型对。

解决方案

可以使用Swift的内省方法来获得:

  func isTuple(b:Any) Bool {
return reflect(b).disposition == MirrorDisposition.Tuple
}

请注意,反射是很大程度上没有记录,可能只支持操场/调试器,但据我知道这是唯一的方法。 / p>




要实现这一点,你需要深入了解 reflect()给你,这是一个符合 MirrorType 的结构,我称之为反射,缺乏一个更好的术语。您可以下标元组的反射来获得元组成员的反射,然后将值返回为 Any 。在这一点上,您可以使用可选的绑定安全地重新发现底层类型:

  func process(value:Any){
println(Any \(value))
}

func process(value:String){
println(String \(value))
}

func processTuple(b:Any) - > Bool {
let isTuple = reflect(b).disposition == MirrorDisposition.Tuple

let r = reflect(b)
for i in 0 ..< r.count {
println(r [i] .0)//字符串保持元组名称:.0,.1等等
println(r [i] .1.value)//该元组的值:aa,1.2

进程(r [i] .1.value)//调用进程(任何)
如果let val = r [i] .1.value as? String {
process(val)// calls process(String)
}
}

return isTuple
}

let myString =aa
let myDouble = 1.2
processTuple((myString,myDouble))//返回false

输出:

  .0 
aa
任何aa
String aa
.1
1.2
任何1.2


What I am actually doing is more complex but it comes down to being able to implement function to detect that something is a tuple, regardless of what the are the types of its elements.

This is my approch that does not work (see comment on last line) :

func isTuple(b: Any) -> Bool {
    return b is (Any, Any)
}

let myString = "aa"
let myDouble = 1.2
isTuple((myString, myDouble)) //returns false

Why doesn't it work? Shouln't Any act as a "wildcard" in tuples as well? Is it a known Swift bug (if not should I consider it one and report)? Is there other way how to make isTupple method work?


EDIT

@NateCook's answer fully answers original question but does it does not help me to do what I am trying to do. This is it:

I need not only to determine that something is a tupple but also to break it into its 2 values without knowing the exact type of those values.

Here is code:

func processIfTuple(b: Any) {
    if reflect(b).disposition == MirrorDisposition.Tuple {
        let (first, second) = b as (Any, Any) //error when casting
        process(first)
        process(second)
    }
}

func process(value: Any) {
    ...
}

processIfTuple(("aa", 1.2))

This does not work from similar reason that the test b is (Any, Any) does not work. This time there is error when trying to cast. Can this be solved? If not should it be considered language bug or missing feature and reported? It definitely leads to a LOT of code duplication because I need to test for all possible pairs of types for a tuple.

解决方案

You can use Swift's baby introspection methods to get at this:

func isTuple(b: Any) -> Bool {
    return reflect(b).disposition == MirrorDisposition.Tuple
}

Note that reflect is largely undocumented and may only be there as support for the playground / debugger, but as far as I know this is the only way to do this.


To achieve this you need to drill down into what reflect() gives you, which is a struct that conforms to MirrorType, which I call a reflection, for lack of a better term. You can subscript the reflection of a tuple to get reflections of the tuples members, and then get the value back out as Any. At that point you can use optional binding to safely rediscover the underlying type:

func process(value: Any) {
    println("Any \(value)")
}

func process(value: String) {
    println("String \(value)")
}

func processTuple(b: Any) -> Bool {
    let isTuple = reflect(b).disposition == MirrorDisposition.Tuple

    let r = reflect(b)
    for i in 0..<r.count {
        println(r[i].0)         // string holding tuple part name: ".0", ".1", etc
        println(r[i].1.value)   // the value of that tuple part: "aa", 1.2

        process(r[i].1.value)   // calls process(Any)
        if let val = r[i].1.value as? String {
            process(val)        // calls process(String)
        }
    }

    return isTuple
}

let myString = "aa"
let myDouble = 1.2
processTuple((myString, myDouble)) //returns false

Output:

.0
aa
Any aa
String aa
.1
1.2
Any 1.2

这篇关于如何检测该参数是两个任意类型的元组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆