购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

3.3 Reduce

在定义一个泛型函数来体现一个更常见的模式之前,我们会先考虑一些相对简单的函数。定义一个计算数组中所有整型值之和的函数非常简单:

可以像下面一样使用 sum 函数:

我们也可以使用类似 sum 中的 for 循环来定义一个 product 函数,用于计算所有数组项相乘之积:

同样地,我们可能想要连接数组中的所有字符串:

或者说,我们可以选择连接数组中的所有字符串,并插入一个单独的首行,以及在每一项后面追加一个换行符:

这些函数有什么共同点呢?它们都将变量 result 初始化为某个值。随后对输入数组 xs 的每一项进行遍历,最后以某种方式更新结果。为了定义一个可以体现所需类型的泛型函数,我们需要对两份信息进行抽象:赋给 result 变量的初始值,以及用于在每一次循环中更新 result 函数

考虑到这一点,我们得出了能够匹配此模式的 reduce 函数定义,如下所示:

这个函数的泛型体现在两个方面:对任意 [Element] 类型的 输入数组 来说,它会计算一个类型为 T 的返回值。这么做的前提是,首先需要一个 T 类型的初始值(赋给 result 变量),以及一个用于更新 for 循环中变量值的函数 combine:(T,Element)-> T 。在一些像OCaml和Haskell一样的函数式语言中, reduce 函数被称为 fold fold_left

我们可以用 reduce 来定义迄今为止本章出现的所有函数。下面是几个例子:

除了写一个闭包,我们也可以将运算符作为最后一个参数。这使得代码更短,如下面两个函数所示:

要再一次说明,我们自定义 reduce 仅仅只是为了练习。Swift的标准库已经为数组提供了 reduce 函数。

我们可以使用 reduce 来定义新的泛型函数。例如,假设有一个数组,它的每一项都是数组,而我们想将它展开为一个单一数组。可以使用 for 循环编写一个函数:

然而,若使用 reduce 则可以像下面这样编写这个函数:

实际上,我们甚至可以使用reduce重新定义 map filter

我们能够使用 reduce 来表示所有这些函数,这个事实说明了 reduce 能够通过通用的方法来体现一个相当常见的编程模式:遍历数组并计算结果。

请务必注意:尽管通过 reduce 来定义一切是一个很有趣的练习,但是在实践中这往往不是一个好主意。原因在于,不出意外的话,你的代码最终会在运行期间大量复制生成的数组,换句话说,它不得不反复分配内存、释放内存,以及复制大量内存中的内容。就像我们之前做的一样,用一个可变结果数组定义 map 的效率显然会更高。理论上,编译器可以优化代码,使其速度与可变结果数组的版本一样快,但是Swift 2.0并没有那么做。如果想了解更多详情,请参阅我们的另一本书——《Swift进阶》 [2] bziAxWJUxrxMVHj+SPdVD3Zvx/x4hLw8e1H8rq9gBvRS3crYthcvwCdb6m8fTNFs

点击中间区域
呼出菜单
上一章
目录
下一章
×