超越面向对象:用函数式思维重塑你的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 技术干货!如果觉得有用,记得收藏本文!

相关推荐
曼巴UE58 小时前
UE FString, FName ,FText 三者转换,再次学习,官方文档理解
服务器·前端·javascript
行走的陀螺仪9 小时前
高级前端 Input 公共组件设计方案(Vue3 + TypeScript)
前端·javascript·typescript·vue·组件设计方案
一颗不甘坠落的流星9 小时前
【Antd】基于 Upload 组件,导入Json文件并转换为Json数据
前端·javascript·json
LYFlied9 小时前
Vue2 与 Vue3 虚拟DOM更新原理深度解析
前端·javascript·vue.js·虚拟dom
Lucky_Turtle10 小时前
【Node】npm install报错npm error Cannot read properties of null (reading ‘matches‘)
前端·npm·node.js
小飞侠在吗10 小时前
vue shallowRef 与 shallowReacitive
前端·javascript·vue.js
惜分飞10 小时前
sql server 事务日志备份异常恢复案例---惜分飞
前端·数据库·php
GISer_Jing11 小时前
WebGL实例化渲染:性能提升策略
前端·javascript·webgl
烟锁池塘柳011 小时前
【技术栈-前端】告别“转圈圈”:详解前端性能优化之“乐观 UI” (Optimistic UI)
前端·ui