本文介绍了SWIFT 1.2中可选展开中的Map和Flat Map差异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

mapflatMap都是在ImplicitlyUnwrappedOptional上发现的,但根据文档,它们的定义(明显)不同:

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

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,它们之间的实际区别是什么?我应该选择哪一个以及何时选择另一个?

推荐答案

(备注:答案已更新,以反映SWIFT 3及更高版本中的语法更改,例如取消ImplicitlyUnwrappedOptional。)

Optional.map()Optional.flatMap()声明如下(我省略了此处不相关的抛出/重新抛出修饰符):

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) -> IntUInt,返回值类型为Int?number不是nil,因此它被解包并传递1到闭包。闭包返回2map返回Optional(2)。如果numbernil,则结果将为nil

现在我们考虑您的第二个示例的一个简化版本,其中包含"flatMap":

let number: Int? = 1
let res2 = number.flatMap { $0 + 1 }
print(res2) // Optional(2)

flatMap应为(Wrapped) -> U?类型的闭包,但{ $0 + 1 }不返回可选的。为了使其进行编译,编译器将其转换为

let res2 = number.flatMap { return Optional($0 + 1) }

现在闭包的类型是(Int) -> Int?U又是Int。同样,number被解包并传递给闭包。闭包返回Optional(2),这也是flatMap的返回值。如果numbernil如果闭包将返回nil,则结果将为nil

因此这些调用之间确实没有区别:

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接受(Wrapped) -> U类型的闭包并转换

Optional<Wrapped>.none          --> Optional<U>.none
Optional<Wrapped>.some(wrapped) --> Optional<U>.some(transform(wrapped))

flatMap接受(Wrapped) -> U?类型的闭包并转换

Optional<Wrapped>.none          --> Optional<U>.none
Optional<Wrapped>.some(wrapped) --> transform(wrapped)

此处transform(wrapped)也可以是Optional<U>.none

如果使用闭包调用flatMap,而不返回可选的,则编译器会自动将其转换为可选的,并且mapmap没有区别。

这篇关于SWIFT 1.2中可选展开中的Map和Flat Map差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-19 06:06