Swift中的函数式编程:从闭包到组合
Swift最初被设计为一种多范式语言。它支持面向对象、面向协议和函数式编程。函数式方法有助于编写更可预测、可测试且并行安全的代码。在本文中,我们将通过实际示例解析Swift中函数式编程的关键概念。
1. 纯函数与不可变性
函数式风格的基础是纯函数。这样的函数对于相同的参数总是返回相同的结果,并且没有副作用(不改变外部状态)。
// 不纯函数 — 修改外部变量var total = 0func addToTotal(_ value: Int) -> Int { total += value return total}
// 纯函数 — 仅进行计算func add(_ a: Int, _ b: Int) -> Int { return a + b}不可变性通过let和具有值语义的结构体实现。我们创建新数组而不是修改原数组:
let numbers = [1, 2, 3, 4, 5]// 替代 var 和 append:let newNumbers = numbers + [6] // [1, 2, 3, 4, 5, 6]2. 闭包作为构建块
Swift中的闭包是可以捕获周围上下文变量的匿名函数。它们是"一等公民":可以作为参数传递并从函数中返回。
// 简单闭包let multiply: (Int, Int) -> Int = { $0 * $1 }let result = multiply(3, 4) // 12
// 捕获上下文的闭包var counter = 0let increment = { counter += 1 }increment() // counter = 1increment() // counter = 2闭包被广泛用于高阶方法,例如sorted:
let names = ["伊万", "安娜", "鲍里斯", "叶莲娜"]let sorted = names.sorted { $0.localizedStandardCompare($1) == .orderedAscending }print(sorted) // ["安娜", "鲍里斯", "叶莲娜", "伊万"]3. 高阶方法:map, filter, reduce
这些是Swift中函数式风格的"主力军"。它们允许在没有显式循环和变异的情况下处理集合。
map
转换集合中的每个元素:
let prices = [100, 200, 300]let withTax = prices.map { $0 * 1.2 }print(withTax) // [120.0, 240.0, 360.0]
// 实际示例:从模型数组中提取名称struct User { let name: String let age: Int}let users = [User(name: "阿列克谢", age: 30), User(name: "玛丽亚", age: 25)]let userNames = users.map { $0.name }print(userNames) // ["阿列克谢", "玛丽亚"]filter
根据条件筛选元素:
let numbers = [1, 2, 3, 4, 5, 6]let evenNumbers = numbers.filter { $0 % 2 == 0 }print(evenNumbers) // [2, 4, 6]
// 筛选年龄大于18岁的用户let adults = users.filter { $0.age >= 18 }reduce
将集合归约为单个值:
let sum = numbers.reduce(0, +) // 21// 从数组构建字符串let words = ["函数式", "编程", "Swift"]let sentence = words.reduce("") { $0.isEmpty ? $1 : $0 + " " + $1 }print(sentence) // "函数式 编程 Swift"组合方法
最有趣的是链式调用:
let transactions = [250, -50, 100, -200, 300, -100]let balance = transactions .filter { $0 > 0 } // 仅收入 .map { $0 * 0.87 } // 扣除13%税 .reduce(0, +) // 求和print(balance) // 565.54. 函数组合与柯里化
组合允许将多个函数合并为一个。Swift没有内置的组合运