Swift4.2高阶函数源码分析
文档更新说明
- 最后更新 2019年02月26日
- 首次更新 2019年02月26日
前言
写这篇文章的时候Swift最新版本是4.2, 网上也有很多源码分析不过已经过时了, 毕竟Swift更新太快了. 本文针对Swift4.2源码做一下高阶函数分析, 如果你一直混淆这几个高阶函数的作用, 或者还不知道他们的作用, 我非常推荐你阅读本文, 这应该是你学习这些新知识最完美的方法了.
Map
源码位置: https://github.com/apple/swift/blob/master/stdlib/public/core/Sequence.swift
1 | @inlinable |
这个源码很简单, 看最后的实操即可, 没什么话说.
flatMap
源码位置: https://github.com/apple/swift/blob/master/stdlib/public/core/SequenceAlgorithms.swift
1 | @inlinable |
上面可以看到flatMap函数的核心代码就是对每一个元素都执行了 append(contentsOf:)方法, 这个方法可以传入一个数组, 数组的元素都会被平铺到result里面.
最终实际效果就是对二维数组调用flatMap后会返回一个一维数组出来.
compactMap
源码位置: https://github.com/apple/swift/blob/master/stdlib/public/core/SequenceAlgorithms.swift
1 | @inlinable // protocol-only |
可以看出来上面的核心代码就是 let newElement = try transform(element) 这句, 这句可以把transform闭包返回的nil元素给过滤掉了.
reduce
源码位置: https://github.com/apple/swift/blob/master/stdlib/public/core/SequenceAlgorithms.swift
1 | @inlinable |
上面源码也是比较简单, 需要注意的是第二个重载函数, 会把运算结果都存在into参数里面去了.下面看实操就比较清楚了.
上面两个重载我们可以看到, Result的类型并不要求一定要和数组元素一样. 这就意味着你可以根据数组元素内容按照闭包的算法, 返回一个想要的其他类型出来.比如下面的例子
1 | let arr = [1,2,3,4,5] |
filter
源码位置: https://github.com/apple/swift/blob/master/stdlib/public/core/Sequence.swift
1 | @inlinable |
filter方法的核心代码就是if try isIncluded(element)这句了, 如果闭包返回true, 则对应元素可以被加入数组, 否则丢掉.
实操
下面我们自己来实现一遍这几个高阶函数, 更好理解他们的用法.
1 | extension Sequence { //这里对Sequence进行扩展而不对Array扩展, 这样也能支持其他遵循Sequence协议的类型, 比如String |
完~