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

相关推荐
微知语5 小时前
Cell 与 RefCell:Rust 内部可变性的双生子解析
java·前端·rust
雨过天晴而后无语5 小时前
Windchill10+html使用Lightbox轻量化wizard的配置
java·前端·html
Yeats_Liao6 小时前
Go Web 编程快速入门 12 - 微服务架构:服务发现、负载均衡与分布式系统
前端·后端·架构·golang
旺仔小拳头..6 小时前
HTML——表单与表格
前端·html
xu_duo_i6 小时前
vue2+elementUI后端返回二进制流,前端下载实现
前端·javascript·elementui
慧一居士6 小时前
在Vue项目中平滑地引入HTML文件
前端·vue.js
我的20096 小时前
HTML常用特殊字符
前端·html
开发者如是说6 小时前
我用 Compose 写了一个 i18n 多语言管理工具
前端·后端·架构
微信api接口介绍6 小时前
微信个人发消息api
运维·服务器·开发语言·前端·网络·微信·ipad