如何检测该参数是两个任意类型的元组? [英] How to detect that parameter is a tuple of two arbitrary types?
问题描述
我实际上做的是更复杂,但是归结到能够实现函数来检测某个元素是一个元组,而不管它的元素是什么类型。
这是我的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屋!