Swift函数式编程:从入门到精通
函数式编程(FP)是一种将计算视为数学函数求值,并避免状态改变和可变数据的编程范式。Swift作为一种多范式语言,完美支持函数式风格,尤其在iOS和macOS开发中。本文将带您从基本概念走向高级技术,如单子和函数组合。
Swift函数式方法基础
函数式编程基于几个关键原则:
- 纯函数——结果仅取决于输入参数,无副作用。
- 数据不可变性——使用
let而非var。 - 函数作为一等公民——可以传递、返回和存储函数。
让我们看一个纯函数的简单示例:
// 纯函数:无副作用func add(_ a: Int, _ b: Int) -> Int { return a + b}
// 使用let result = add(3, 5) // 8print(result)闭包和高阶函数
闭包(closures)是自包含的功能块,可以在代码中传递和使用。它们是使用高阶函数的基础。
// 简单闭包let multiply = { (x: Int, y: Int) -> Int in return x * y}
let product = multiply(4, 7) // 28print(product)Swift为集合操作提供了强大的高阶函数:
map
map对数组的每个元素应用变换:
let numbers = [1, 2, 3, 4, 5]let squared = numbers.map { $0 * $0 }print(squared) // [1, 4, 9, 16, 25]filter
filter筛选出满足条件的元素:
let evenNumbers = numbers.filter { $0 % 2 == 0 }print(evenNumbers) // [2, 4]reduce
reduce将所有元素合并为一个值:
let sum = numbers.reduce(0, +)print(sum) // 15函数组合和柯里化
函数组合允许将简单函数组合成更复杂的函数。Swift没有内置的组合运算符,但很容易实现:
// 组合运算符precedencegroup CompositionPrecedence { associativity: left higherThan: AssignmentPrecedence}
infix operator >>>: CompositionPrecedence
func >>> <A, B, C>(left: @escaping (A) -> B, right: @escaping (B) -> C) -> (A) -> C { return { right(left($0)) }}
// 使用func double(_ x: Int) -> Int { x * 2 }func toString(_ x: Int) -> String { "\\(x)" }
let doubleThenString = double >>> toStringprint(doubleThenString(5)) // "10"柯里化是将接受多个参数的函数转换为一系列每个只接受一个参数的函数:
// 普通函数func add(_ a: Int, _ b: Int) -> Int { a + b }
// 柯里化版本func curriedAdd(_ a: Int) -> (Int) -> Int { return { b in a + b }}
let addFive = curriedAdd(5)print(addFive(3)) // 8Swift中的单子和函子
在函数式编程中,函子是可以被映射(map)的类型。单子是带有额外flatMap(或>>=)操作的函子。Swift中最著名的例子是Optional和Array。
Optional作为单子
let optionalValue: Int? = 5
// map — 如果值不为nil则应用函数let doubled = optionalValue.map { $0 * 2 }print(doubled) // Optional(10)
// flatMap