超越面向对象:用函数式思维重塑你的Lua代码

一、函数是"一等公民"

这是 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

二、核心原则:纯函数与不可变性

函数式编程推崇两个重要原则:

  1. 纯函数 (Pure Functions)

    • 相同的输入永远产生相同的输出。
    • 没有任何可观察到的副作用。 副作用是指修改函数外部的状态,比如修改全局变量、打印到控制台、写入文件、修改传入的表等。
  2. 不可变性 (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 技术干货!如果觉得有用,记得收藏本文!

相关推荐
wearegogog1236 小时前
基于 MATLAB 的卡尔曼滤波器实现,用于消除噪声并估算信号
前端·算法·matlab
Drawing stars6 小时前
JAVA后端 前端 大模型应用 学习路线
java·前端·学习
品克缤6 小时前
Element UI MessageBox 增加第三个按钮(DOM Hack 方案)
前端·javascript·vue.js
小二·6 小时前
Python Web 开发进阶实战:性能压测与调优 —— Locust + Prometheus + Grafana 构建高并发可观测系统
前端·python·prometheus
小沐°6 小时前
vue-设置不同环境的打包和运行
前端·javascript·vue.js
qq_419854057 小时前
CSS动效
前端·javascript·css
烛阴7 小时前
3D字体TextGeometry
前端·webgl·three.js
桜吹雪7 小时前
markstream-vue实战踩坑笔记
前端
C_心欲无痕8 小时前
nginx - 实现域名跳转的几种方式
运维·前端·nginx
花哥码天下8 小时前
恢复网站console.log的脚本
前端·javascript·vue.js