Swift 1.2中可选展开的Map和flatMap差异

时间:2015-04-10 08:24:00

标签: swift dictionary bind optional flatmap

mapflatMap都在ImplicitlyUnwrappedOptional上定义,但根据文档的说明,它们的定义明显不同:

  

func map(f:@noescape(T) - > U) - > ü!

     

如果self == nil,则返回nil。否则,返回f(self!)。

     

func flatMap(f:@noescape(T) - > U!) - > ü!

     

返回f(self)! iff self和f(self)不是nil。

我尝试使用它们的一个简单例子:

let number: Int? = 1

let res1 = number.map { $0 + 1 }.map { $0 + 1 }
let res2 = number.flatMap { $0 + 1 }.flatMap { $0 + 1 }

res1 //3
res2 //3

但即使numbernil.,他们也会产生相同的结果 所以我的问题是,如果我将mapflatMap应用于ImplicitlyUnwrappedOptional,它们之间的实际差异是什么?我应该选择哪一个以及何时?

3 个答案:

答案 0 :(得分:7)

flatMap()中,映射闭包的类型为(T) -> U?并且可以 返回nil

let res3 = number.flatMap { $0 == 1 ? nil : 2 }.flatMap { $0 + 1 }
res3 // nil

对于映射闭包具有的map(),这是不可能的 签名(T) -> U

更现实的例子是可选字符串的转换 到可选的整数:

func foo(s : String?) -> Int? {
    return s.flatMap { $0.toInt() }
}
foo("1") // 1
foo("x") // nil (because `toInt()` returns nil)
foo(nil) // nil (because argument is nil)

答案 1 :(得分:4)

  

对于映射闭包具有签名map()的{​​{1}},这是不可能的。

那不太对劲。在我看来,Martin R的答案并没有完全解决问题的核心,即文档没有正确描述(T) -> Umap之间的区别。

区别在于他们采取何种封闭措施。每个人都会愉快地接受一个产生一个nonOptional的闭包或一个产生一个Optional的闭包 - 尽管文档说的是什么,尽管它们的声明有所不同。所有这些表达式都编译成:

flatMap

是的,那么实际的区别是什么?这是let i : Int? = nil let result1 = i.map {_ in "hello"} // map, closure produces nonOptional let result2 = i.flatMap {_ in "hello"} // flatMap, closure produces nonOptional let result3 = i.map {_ in Optional("hello") } // map, closure produces Optional let result4 = i.flatMap {_ in Optional("hello") } // flatMap, closure produces Optional 所做的,以防闭包 生成一个Optional:它解包它,从而防止双重包装可选:

flatMap

这是map和flatMap之间唯一的区别。

答案 2 :(得分:0)

flatMap 解析嵌套的选项,而 map 不解析。

平面图

var temp: Int? = 3
var flag: Bool = false
print(temp.flatMap { $0 < 5 ? 1 : nil } ?? .zero) 

// output: 1

地图

var temp: Int? = 3
var flag: Bool = false
print(temp.map { $0 < 5 ? 1 : nil } ?? .zero) 

// output: Optional(Optional(1))