一、函数是"一等公民"
这是 Lua 能够进行函数式编程的根本前提。这意味着函数和其他数据类型(如数字、字符串、表)的地位完全一样:
- 可以被赋值给变量
- 可以作为参数传递给其他函数
- 可以作为其他函数的返回值
- 可以存储在数据结构(如表)中
lua
-- 1. 赋值给变量
local greet = function(name)
print("Hello, " .. name)
end
-- 2. 作为参数传递
function call_twice(func, arg)
func(arg)
func(arg)
end
call_twice(greet, "Alice") -- "greet" 函数被当作参数传递
-- 3. 作为返回值
function create_adder(x)
return function(y) -- 返回一个新的函数
return x + y
end
end
local add_five = create_adder(5) -- add_five 现在是一个会加5的函数
print(add_five(10)) -- 输出: 15
二、核心原则:纯函数与不可变性
函数式编程推崇两个重要原则:
-
纯函数 (Pure Functions):
- 相同的输入永远产生相同的输出。
- 没有任何可观察到的副作用。 副作用是指修改函数外部的状态,比如修改全局变量、打印到控制台、写入文件、修改传入的表等。
-
不可变性 (Immutability):
- 数据一旦创建,就不应被更改。
- 当需要"修改"数据时,函数式的方法是创建一个包含新值的副本。
- 这使得代码的行为非常可预测。你不必担心一个表在传递给某个函数后,其内容会被意外地篡改。
虽然 Lua 本身并不强制要求不可变性(table 是可变的),但在实践函数式风格时,我们应该自觉地遵循这个原则。
三、函数式编程的三大高阶函数:Map, Filter, Reduce
高阶函数(Higher-Order Function)是指那些接受函数作为参数或返回函数的函数。map, filter, reduce 是函数式编程工具箱中最经典的三件套。
由于 Lua 标准库没有内置它们,我们可以轻易地自己实现。
1. Map
map 函数接收一个列表和一个转换函数,然后对列表中的每一个元素应用该函数,最后返回一个包含所有新结果的新列表。
lua
function map(list, func)
local new_list = {}
for i, v in ipairs(list) do
new_list[i] = func(v)
end
return new_list
end
local numbers = {1, 2, 3, 4}
local squares = map(numbers, function(n) return n * n end)
-- squares is now {1, 4, 9, 16}
-- 原始的 numbers 列表没有被改变
2. Filter
filter 函数接收一个列表和一个断言函数(返回 true 或 false),然后返回一个只包含那些使断言函数返回 true 的元素的新列表。
lua
function filter(list, predicate)
local new_list = {}
for _, v in ipairs(list) do
if predicate(v) then
table.insert(new_list, v)
end
end
return new_list
end
local numbers = {1, 2, 3, 4, 5, 6}
local evens = filter(numbers, function(n) return n % 2 == 0 end)
-- evens is now {2, 4, 6}
3. Reduce
reduce 函数最具威力。它接收一个列表、一个聚合函数和一个初始值。它会遍历列表,反复将当前元素和累积结果传入聚合函数,最终将列表 "减少"为一个单一的值。
lua
function reduce(list, func, initial)
local accumulator = initial
for _, v in ipairs(list) do
accumulator = func(accumulator, v)
end
return accumulator
end
local numbers = {1, 2, 3, 4}
local sum = reduce(numbers, function(acc, current) return acc + current end, 0)
-- sum is 10 ((((0+1)+2)+3)+4)
local product = reduce(numbers, function(acc, current) return acc * current end, 1)
-- product is 24 ((((1*1)*2)*3)*4)
结语
点个赞,关注我获取更多实用 Lua 技术干货!如果觉得有用,记得收藏本文!