Swift中的函数式编程
如果我们查找有关函数式编程的文章,则其中大多数都在谈论高级函数式编程,例如副作用,无状态,不变性或monad之类的内容 ,而其他基本示例(例如map的工作方式)则太简单了,但是在这里试图通过使用Swift中的示例来展示函数式编程的实用方面。
这篇文章的第一部分将为您简要概述函数式编程和基本定义。 示例部分显示了如何以功能样式编写命令性非功能代码。
高阶函数
函数式编程语言的第一个显着区别是,可以将函数分配给值并传递给其他函数。 这就是为什么他们被称为头等公民。 当您说一种语言具有一流的功能时,这意味着它将一种功能视为值,您可以将一个功能分配给一个变量,或者将其传递。 一流的功能被视为一个对象。
有一个更高层次的功能。 它们接受一个或多个函数作为参数或返回其他函数。 高阶函数是可以在其他函数上使用的函数,即它们将函数作为参数,也可以返回一个函数。
映射,过滤,缩小
Map是著名的高阶函数之一。 Map在数组(更确切地说是集合)上工作,它接受一个函数(称为transform)作为参数,并将此transform
函数应用于每个元素,并返回结果数组,作为“ transformed”元素的新数组。
使用map
有一些优点:它更短并且需要更少的代码 , 更少的错误空间 ,更重要的是它更干净 。
假设我们有一个字符串数组,要计算每个字符,我们必须1.遍历该数组,2.获取每个元素的计数,3.将其追加到新数组中:
let houses = ["Stark", "
Baratheon", "
Targaryen", "L
annister"]
var letterCounts:[Int] = []
用于房屋{
letterCounts.append(item.count)
}
print(letterCounts)// [5, 9, 9, 9]
5,9,9,9// [5, 9, 9, 9]
显然,功能性方法更为简洁:
let letterCounts = houses.map { $0.count } // [5, 9, 9, 9]
Filter接受一个函数includeElement
,遍历数组并返回一个仅包含那些符合此条件的元素的数组。 给定的闭包采用该元素并返回Bool
值,该值指示该元素是否与条件匹配。 其签名如下所示:
func filter(_ includeElement:(Element)-> Bool)-> [Element]
假设我们有一个包含一些质数的数组,我们想复制那些比理想平方小一个的数。 命令式解决方案很容易,只需查看质数数组并检查它是否是一个完美的平方(与n-1的完美平方n的按位与总是为0):
让素数:[Int] = [2,3,5,7,11,11,13,17,...,79,83,89,97]
var mersenne:[Int] = []
对于素数为p的素数,其中Int(p)&Int(p + 1)== 0 {
mersenne.append(p)
}
// mersenne [3,7,31]
您可以使用filter在一行中缩短整个for循环:
let mersenne = primes.filter {Int($ 0)&Int($ 0 + 1)== 0}
Filter
仅返回可以满足关闭条件的元素组成的数组。
降低
Reduce将所有元素组合为一个值(例如,将所有元素加总)。 它对一个累加器和数组中的每个元素应用一个函数,以将其减少为单个值。 它具有两个参数,即初始值和用于将累积值与元素组合的函数。 在总结数组元素的情况下,我们可以将其写为:
let sum = array.reduce(0){总计,总计num + num}
或仅传递运算符array.reduce(0, +)
因为运算符是函数。