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. 选择合适的类型是性能优化的关键

相关推荐
半夏知半秋4 小时前
skynet debug_console控制台中debug指令使用
服务器·开发语言·学习·lua
h7997108 小时前
redis lua脚本(go)调用教程以及debug调试
redis·golang·lua
玩转C语言和数据结构3 天前
Lua下载和安装教程(附安装包)
lua·lua下载·lua安装教程·lua下载和安装教程·lua安装包
Arva .3 天前
HTTP Client
网络协议·http·lua
爱吃小胖橘4 天前
Lua语法(2)
开发语言·unity·lua
ellis19705 天前
LuaC API知识点汇总
unity·lua
爱吃小胖橘8 天前
Lua语法
开发语言·unity·lua
东方芷兰8 天前
JavaWeb 课堂笔记 —— 20 SpringBootWeb案例 配置文件
java·开发语言·笔记·算法·log4j·intellij-idea·lua
1nullptr8 天前
Lua上值与闭包
开发语言·lua