Lua迭代器与泛型for

在Lua中,迭代器是一种强大的编程模式,它允许我们以统一的方式遍历各种数据结构。迭代器的核心思想是将遍历逻辑封装起来,提供简洁的接口来访问集合中的元素。

迭代器的基本概念

什么是迭代器?

在Lua中,迭代器本质上是一个函数,每次调用这个函数会返回下一个元素。一个完整的迭代器包含两部分:

  1. 闭包(迭代器)本身:负责返回下一个元素
  2. 工厂函数:创建闭包及其内部变量的函数

基本实现示例

lua 复制代码
function values(t)
    local i = 0
    return function()
        i = i + 1
        if i <= #t then
            return t[i]
        else
            return nil 
        end
    end
end

在这个例子中:

  • values工厂函数
  • 返回的匿名函数是迭代器(闭包)
  • i状态变量,被闭包捕获

使用迭代器

手动调用方式
lua 复制代码
t = {1, 2, 3, 4, 5}
iter = values(t)
while true do
    local element = iter()
    if element == nil then break end
    print(element)
end
泛型for方式(推荐)
lua 复制代码
for element in values(t) do 
    print(element)
end

泛型for语法更加简洁,Lua内部会自动管理迭代器的生命周期。

泛型for的内部机制

语法结构

lua 复制代码
for var-list in exp-list do 
    body
end

详细语法

lua 复制代码
for var1, var2, ... in iterator_func, state, initial_value do
    -- 循环体
end

内部实现机制

泛型for在内部保存了三个值:

  1. 迭代函数(iterator function)
  2. 不可变状态(invariant state)
  3. 控制变量(control variable)

上述语法等价于:

lua 复制代码
do
    local _f, _s, _var = explist
    while true do
        local var_1, ..., var_n = _f(_s, _var)
        _var = var_1
        if _var == nil then break end
        block
    end
end

无状态迭代器

概念

无状态迭代器(stateless iterator)是一种自身不保存任何状态的迭代器。所有的状态信息都通过参数传递,使得迭代器函数本身是纯函数。

基本实现

lua 复制代码
local function iter(t, i)
    i = i + 1
    local v = t[i]
    if v then
        return i, v
    end
end

function ipairs(t)
    return iter, t, 0
end

链表遍历示例

lua 复制代码
local function getnext(list, node)
    if not node then
        return list
    else
        return node.next
    end
end

function traverse(list)
    return getnext, list, nil
end

注意 :初始变量值是nil而不是list,这是链表遍历的关键。

按键排序遍历表

lua 复制代码
function pairsByKeys(t, f)
    local a = {}
    for n in pairs(t) do
        a[#a + 1] = n 
    end
    table.sort(a, f)
    local i = 0
    return function()
        i = i + 1
        return a[i], t[a[i]]
    end
end

for name, line in pairsByKeys(lines) do
    print(name, line)
end

有状态迭代器

概念

有状态迭代器通过闭包保存状态信息,每次调用时访问和修改内部状态。

基本结构

lua 复制代码
for var1, var2, ... in iterator_func() do
    -- 循环体
end

内部机制

lua 复制代码
function iterator_func()
    local state = initial_state  -- 状态变量
    return function()
        -- 访问和修改状态
        -- 返回下一个值或nil
    end
end

实现示例

lua 复制代码
function stateful_squares(max)
    local count = 0  -- 状态变量
    return function()
        count = count + 1
        if count <= max then
            return count, count * count
        else
            return nil
        end
    end
end

for i, square in stateful_squares(3) do
    print(i .. " 的平方是 " .. square)
end

两种迭代器的对比

无状态迭代器

优势:

  • 线程安全:无状态,可并发使用
  • 内存效率:不保存状态,内存占用少
  • 可重入:可以同时使用多个实例
  • 函数式:纯函数,易于测试

适用场景:

  • 数学计算:斐波那契数列、素数生成
  • 数据转换:数组映射、过滤
  • 多线程环境:并发处理
  • 内存敏感应用:嵌入式系统

有状态迭代器

优势:

  • 实现简单:状态管理直观
  • 性能优化:状态访问快速
  • 灵活性:可以保存复杂状态

劣势:

  • 不可重入:不能同时使用多个实例
  • 线程不安全:状态共享问题
  • 内存开销:需要保存状态

适用场景:

  • 文件处理:逐行读取文件
  • 网络流:处理数据流
  • 复杂状态:游戏状态机
  • 一次性遍历:数据处理管道

实际应用示例

文件行迭代器

lua 复制代码
function lines(filename)
    local file = io.open(filename, "r")
    if not file then return nil end
    
    return function()
        local line = file:read()
        if not line then
            file:close()
            return nil
        end
        return line
    end
end

-- 使用
for line in lines("data.txt") do
    print(line)
end

范围迭代器

lua 复制代码
function range(start, stop, step)
    step = step or 1
    local current = start - step
    
    return function()
        current = current + step
        if step > 0 and current <= stop then
            return current
        elseif step < 0 and current >= stop then
            return current
        else
            return nil
        end
    end
end

-- 使用
for i in range(1, 10, 2) do
    print(i)  -- 输出: 1, 3, 5, 7, 9
end

应用

1. 选择合适的迭代器类型

  • 简单遍历:使用无状态迭代器
  • 复杂状态:使用有状态迭代器
  • 并发环境:优先选择无状态迭代器

2. 错误处理

lua 复制代码
function safe_iterator(data)
    local index = 0
    return function()
        index = index + 1
        if index <= #data then
            return data[index]
        else
            return nil
        end
    end
end

3. 性能优化

lua 复制代码
-- 避免在循环中创建新表
function efficient_pairs(t)
    local keys = {}
    for k in pairs(t) do
        keys[#keys + 1] = k
    end
    table.sort(keys)
    
    local i = 0
    return function()
        i = i + 1
        local k = keys[i]
        if k then
            return k, t[k]
        end
    end
end

总结

Lua的迭代器机制提供了强大而灵活的遍历能力:

  1. 泛型for简化了迭代器的使用
  2. 无状态迭代器适合并发和函数式编程
  3. 有状态迭代器适合复杂状态管理
  4. 选择合适的类型是性能优化的关键

相关推荐
玖玥拾2 天前
Lua 基础语法(八) Unity Huatuo (HybridCLR)
开发语言·unity·游戏引擎·lua
x10n92 天前
Postman 汉化完整指南
测试工具·lua·postman
AI情绪识别开源4 天前
检信 Allemotion 认知功能障碍矫正软件体验评审意见报告
lua
玖玥拾4 天前
Lua 基础语法(六)xLua Lua 调用 C# 交互
开发语言·unity·c#·lua
玖玥拾5 天前
Lua 基础语法(五)Unity xLua基础配置与 C# 访问 Lua
开发语言·unity·c#·lua
玖玥拾6 天前
Lua 基础语法(二)
开发语言·unity·lua
玖玥拾6 天前
Lua 基础语法(三) 元表 metatable、元方法、模拟面向对象
开发语言·unity·lua
盟道科技7 天前
Redis+Lua 实现滑动窗口限流:从固定窗口踩坑到生产可用的完整方案
redis·junit·lua
Rain的Java大神之路10 天前
高并发下的热点账户余额扣减:Redis+Lua脚本实现无锁记账
java·spring boot·redis·后端·spring cloud·缓存·lua
qq_3227627512 天前
一个接口从能用到稳定,中间差的到底是什么
服务器·开发语言·lua·接口·fastapi·请求