Swift 4.1 迁移小技巧 —— CompactMap

Swift 4.1 中引入了一个“新”函数 compactMap,在这里给你们介绍一个迁移的小技巧。html

compactMap 的由来

在开始以前,先简单介绍一下 compactMap 的由来,咱们都知道以前 flatMap 有两个重载版本,第一个是用来 flat 集合的:git

let arr = [[1, 2, 3], [4, 5]]

let newArr = arr.flatMap { $0 }
// newArr 的值为 [1, 2, 3, 4, 5]
复制代码

第二个是用来 flat 可选值的:github

let arr = [1, 2, 3, nil, nil, 4, 5]

let newArr = arr.flatMap { $0 }
// newArr 的值为 [1, 2, 3, 4, 5]
复制代码

这两个版本虽然都是用来降维的,但第二个版本除了 flat 以外其实还有 filter 的做用,在使用时容易产生歧义,因此社区认为最好把第二个版本从新拆分出来,使用一个新的方法命名,就产生了这个提案 SE-0187swift

最初这个提案用了 filterMap 这个名字,但后来通过讨论,就决定参考了 Ruby 的 Array::compact 方法,使用 compactMap 这个名字。app

迁移小技巧

虽然就 API 层面来讲,这只是单纯的名字修改,但全局替换很难实现,而逐个编译警告处理又太过麻烦,在这里我想介绍一个更加便捷的迁移方法:构造一个 flatMap 来重载标准库的实现,而后再借助 Xcode 的重构工具对函数进行重命名。ide

方式很直白,惟一的问题在于如何重载,首先看一下 flatMap 的声明,flatMap 是声明在 Sequence 类型里的:函数

// stdlib/public/core/SequenceAlgorithms.swift
extension Sequence {

  @inline(__always)
  @available(swift, deprecated: 4.1, renamed: "compactMap(_:)",
    message: "Please use compactMap(_:) for the case where closure returns an optional value")
  public func flatMap<ElementOfResult>( _ transform: (Element) throws -> ElementOfResult?
  ) rethrows -> [ElementOfResult] {
    return try _compactMap(transform)
  }
}
复制代码

再参考我以前的博文【译】Swift 泛型宣言工具

...ui

参考 Swift 官方文档 Protocols 小节里的最后一段:spa

“If a conforming type satisfies the requirements for multiple constrained extensions that provide implementations for the same method or property, Swift will use the implementation corresponding to the most specialized constraints.”

约束越多的 conformance 优先级越高

...

综上可得,因为 flatMap 是一个声明在 Sequence 里的泛型函数,因此咱们能够在一个约束更多的 extension 里声明一个 flatMap 进行重载,例如继承自 SequenceCollection

protocol Collection: Sequence {}
复制代码

又或者是某个 Nested Type,例如 Array,鉴于咱们项目里基本上都是使用 Array.flatMap,因此直接重载便可:

extension Array {

  func flatMap<ElementOfResult>( _ transform: (Element) throws -> ElementOfResult?
  ) rethrows -> [ElementOfResult] {
    return try compactMap(transform)
  }
}
复制代码

接着右键 -> Refactor -> Rename,把 flatMap 改为 compactMap

最后把咱们刚刚重载的方法删掉,迁移完成了!!!

以为文章还不错的话能够关注一下个人博客

相关文章
相关标签/搜索