map
和flatMap
都在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
但即使number
为nil.
,他们也会产生相同的结果
所以我的问题是,如果我将map
或flatMap
应用于ImplicitlyUnwrappedOptional
,它们之间的实际差异是什么?我应该选择哪一个以及何时?
答案 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) -> U
和map
之间的区别。
区别在于不他们采取何种封闭措施。每个人都会愉快地接受一个产生一个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))