地图和平面地图的定义都是隐含的,但根据文档,它们的定义(显然)不同:
Func地图(f:@noscape(T)-
如果self==nil,则返回nil。否则,返回f(self!)。
Func平面地图(f:@noscape(T)-
返回f(self)!iff self和f(self)不是零。
我试着用一个简单的例子来使用它们:
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
但即使数字为零,它们也产生了相同的结果
map或flatMap
应用于ImplicitlyUnwrappedOptional,它们之间的实际区别是什么?我应该选择哪一个,何时选择?
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))
这在映射闭包具有签名(T)的映射中是不可能的-
这不太正确。在我看来,Martin R的答案并没有完全触及问题的核心,那就是文档没有正确描述地图和平面地图之间的区别。
区别不在于他们采取什么样的收尾方式。每个人都会乐于接受一个生成非可选的闭包或一个生成可选的闭包——不管文档怎么说,也不管它们的声明有什么不同。所有这些表达式都可以编译:
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
好吧,那么实际的区别是什么?这是当闭包确实生成可选对象时,flatMap所做的:它将其展开,从而防止出现双重包装的可选对象:
let i : Int? = nil
let result1 = i.map {_ in "hello"} // String?
let result2 = i.flatMap {_ in "hello"} // String?
let result3 = i.map {_ in Optional("hello") } // String?? // double-wrapped
let result4 = i.flatMap {_ in Optional("hello") } // String? // not double-wrapped
这是map和flatMap之间的唯一区别。
(备注:答案已更新,以反映Swift 3及更高版本中的语法变化,例如取消了隐式附加(ImplicitlyUnwrappedOptional)
)
Optional.map()
和Optional.flatMap()
声明如下(我省略了这里不相关的throws/rethrows修饰符):
func map<U>(_ transform: (Wrapped) -> U) -> U?
func flatMap<U>(_ transform: (Wrapped) -> U?) -> U?
让我们考虑使用“map”的第一个示例的简化版本:
let number: Int? = 1
let res1 = number.map { $0 + 1 }
print(res1) // Optional(2)
number
具有Int?
类型,闭包类型推断为(Int)-
现在,我们考虑第二个示例的简化版本“flatMap”:
let number: Int? = 1
let res2 = number.flatMap { $0 + 1 }
print(res2) // Optional(2)
flatMap
需要类型为的闭包(已包装)-
let res2 = number.flatMap { return Optional($0 + 1) }
现在闭包的类型为(Int)-
因此,这些调用之间确实没有区别:
let res1 = number.map { $0 + 1 }
let res2 = number.flatMap { $0 + 1 }
然而,这并不是flatMap的本意。更现实的例子是
func foo(_ s : String?) -> Int? {
return s.flatMap { Int($0) }
}
print(foo("1")) // Optional(1)
print(foo("x")) // nil (because `Int($0)` returns nil)
print(foo(nil)) // nil (because the argument is nil)
通常,
map
采用类型为的闭包(已包装)-
Optional<Wrapped>.none --> Optional<U>.none
Optional<Wrapped>.some(wrapped) --> Optional<U>.some(transform(wrapped))
平面图
采用类型的闭包(包装)-
Optional<Wrapped>.none --> Optional<U>.none
Optional<Wrapped>.some(wrapped) --> transform(wrapped)
此处可以选择变换(包裹)
如果(如您的示例所示)使用不返回可选值的闭包调用了
flatMap,那么编译器会自动将其转换为可选值,与映射没有任何区别。
这两种方法有什么区别:和? 请举个例子。
问题内容: 在Xcode 8发行版中,我发现了一个奇怪的场景。 这是代码, 结果如下: 上面的这些表明,当我为没有显式类型的变量分配一个 隐式解包的optional时 ,该类型将被推断为一个可选类型,而不是它最初的类型,也就是 隐式解开的optional 。 我的Xcode已更新至8。任何人都可以验证Xcode 7.x中的行为吗? 更改是由于Swift版本更改还是Xcode? 问题答案: 这是SE
如果像Apple在Swift编程中所说的隐式展开选项应该总是有一个值,那么为什么不使用非选项来代替呢?我知道非选项不能赋值为nil,但还有其他区别吗?
似乎在Swift 4.1中已弃用。但是在Swift 4.1中有一个新方法正在做同样的事情?使用,您可以转换集合中的每个对象,然后删除任何为nil的项目。 喜欢平面图 像compactMap compactMap也在做同样的事情。 这两种方法有什么区别?为什么苹果决定重命名该方法?
问题内容: 为什么无法对隐式解包的可选变量进行突变? 这是一个重现问题的简短示例: 带整数 问题答案: 更新: Xcode Beta 5中的一个小警告已解决此问题: 该数组可以按预期工作,但是现在看来整数仍然需要显式拆包以允许使用 当前,这仅仅是Optionals的本质(无论是否隐式解包)。unwrap运算符返回一个不变的值。这可能是固定的,或者将来会提供更好的解决方案。 目前唯一的解决方法是将数
在Swift 4.0中,以下代码不可编译: 现在我想象是