我们可以定义一个函数来拆除可选的末日金字塔,而不是使用多个可选绑定。
func if_let<T, U, V> (a: T?, _ b: U?, _ c: V?, fn:(T, U, V) -> () ){
if let a = a {
if let b = b {
if let c = c {
fn(a, b, c)
}
}
}
}
然后我可以这样写:
var s1: String? = "s11"
var s2: String? = "s22"
var s3: String? = "s33"
if_let(s1, s2, s3) { s1, s2, s3 in
print(("(s1) - (s2) - (s3)"))
}
然而,问题是如何使这个if_let
函数更通用,以便它可以接受任意数量的参数。我的实现是这样的:
func if_let<T> (values: T?..., fn:(params: [T]) -> ()) {
for value in values {
guard value != nil else { return }
}
let unwrappedArray = values.map{ $0! }
fn(params: unwrappedArray)
}
我试着映射数组,得到一个所有元素都展开的新数组,然后调用fn
。但当我再次运行测试时,我得到了一个编译错误:
无法将类型为
String?
的值转换为所需的参数类型"_?"
有人能解释并纠正这个错误吗?
问题是if_let
的第二个实现不再将(T,U,V)->()
类型的函数作为最终参数。它现在需要一个类型为([T])->()
的函数。如果你用一个调用它,它会编译:
if_let(s1, s2, s3) { args in // or: (args: [String])->() in
print("(args[0]) - (args[1]) - (args[2])")
}
一个相关的注释,而不是对特定问题的回答:有了Swift 2,你就不必再进入末日金字塔了
let a: String? = nil
let b: Int? = nil
let c: Double? = nil
// possible mutate...
if let a = a, b = b, c = c {
// do something with shadow vars
}