当前位置: 首页 > news >正文

Lua-迭代器

1. 迭代器与闭包的结合

迭代器是用于遍历集合元素的机制,在 Lua 中通常以函数 + 闭包的形式实现。闭包可以 “记住” 遍历的状态(如当前位置、已读内容等),从而在每次调用时返回 “下一个元素”。

  • 示例:为列表创建返回元素值的迭代器
    function values(t)local i = 0return function()  -- 闭包:保存状态变量 ii = i + 1return t[i]end
    end
    
    这里 values 是 “迭代器工厂”,每次调用会创建一个闭包,闭包通过 i 记录遍历位置,每次调用返回列表的下一个元素,直到返回 nil 表示遍历结束。

2. 泛型 for 的语义与工作机制

泛型 for 是 Lua 专门为迭代器设计的语法糖,它会自动处理迭代器的调用和状态管理,简化遍历逻辑。

  • 语法形式:for <var-list> in <exp-list> do <body> end
  • 工作原理:泛型 for 会先对 <exp-list> 求值,期望得到三个值迭代器函数恒定状态控制变量初始值。随后,for 会反复调用迭代器函数,将返回值赋值给 <var-list>,直到迭代器返回 nil 时结束循环。
  • 等价逻辑(帮助理解):
    -- 泛型 for 语法
    for var_1, ..., var_n in <explist> do <block> end-- 等价的手动实现
    dolocal _f, _s, _var = <explist>  -- 分别对应:迭代器函数、恒定状态、控制变量初始值while true dolocal var_1, ..., var_n = _f(_s, _var)_var = var_1if _var == nil then break end<block>end
    end
    

3. 无状态迭代器

与依赖闭包保存状态的迭代器不同,无状态迭代器自身不保存遍历状态,而是通过泛型 for 传递的 “恒定状态” 和 “控制变量” 来确定下一个元素。

  • 示例:ipairs 就是典型的无状态迭代器,它通过 “恒定状态(数组本身)” 和 “控制变量(当前索引)” 来遍历数组:
    a = {"one", "two", "three"}
    for i, v in ipairs(a) doprint(i, v)
    end

“无状态迭代器” 是 Lua 中一种特殊的迭代器,核心特点是自身不保存任何遍历状态(比如当前位置、进度等),所有状态都通过泛型 for 循环来传递和维护。这听起来有点抽象,我们用具体例子和对比来理解:

先看一个 “有状态迭代器”(依赖闭包保存状态)

之前讲的计数器迭代器就是典型的 “有状态”,它用闭包中的变量(比如 i)保存当前遍历位置:

-- 有状态迭代器:用闭包的 i 保存遍历位置
function iter(t)local i = 0  -- 状态变量(保存在闭包中)return function()i = i + 1return t[i]end
end-- 使用:每次调用迭代器,都依赖闭包中的 i 推进
local t = {"a", "b", "c"}
local it = iter(t)  -- 创建迭代器(闭包)
print(it())  --> a(i=1)
print(it())  --> b(i=2)
print(it())  --> c(i=3)

这里的 “状态”(i)被闭包 “记住”,迭代器自己知道下一步该遍历哪里。

再看 “无状态迭代器”:状态由 for 循环传递

无状态迭代器不自带状态,它的每次调用都需要外部提供 “当前状态”,并返回 “下一个状态”。最典型的例子就是 ipairs(用于遍历数组):

-- 模拟 ipairs 的无状态迭代器实现
function my_ipairs(t, i)  -- t 是数组(恒定状态),i 是当前索引(变化的状态)i = i + 1  -- 从当前索引推进到下一个local v = t[i]  -- 获取下一个值if v then  -- 如果存在值,返回索引和值(下一个状态)return i, vend  -- 否则返回 nil,结束循环
end-- 泛型 for 循环使用无状态迭代器
local t = {"a", "b", "c"}
-- for 循环会自动传递状态:初始 i=0,每次调用 my_ipairs(t, i)
for i, v in my_ipairs, t, 0 doprint(i, v)
end

输出:

1   a
2   b
3   c

无状态迭代器的核心逻辑:

  1. 三个关键角色

    • 迭代器函数(如 my_ipairs):负责计算下一个元素,接收两个参数 ——恒定状态(不会变的,比如数组 t)和 当前状态(会变的,比如索引 i)。
    • 恒定状态(如 t):整个遍历过程中不变的量,通常是被遍历的集合本身。
    • 当前状态(如 i):记录遍历进度,每次迭代后更新,作为下一次调用的参数。
  2. 泛型 for 的自动协作

    • 第一次调用:for 会用 恒定状态(t) 和 初始状态(0) 调用迭代器,得到 i=1, v=a
    • 第二次调用:for 会用 恒定状态(t) 和 上一次返回的 i=1 调用迭代器,得到 i=2, v=b
    • 直到迭代器返回 nil,循环结束。
  3. 为什么叫 “无状态”:迭代器函数(my_ipairs)本身不保存任何状态(没有闭包变量、全局变量记录 i),所有状态(i)都由 for 循环传递,每次调用都是 “无记忆” 的,完全依赖输入的 i 来计算下一步。

无状态迭代器的优势:

  • 更轻量:不需要闭包来保存状态,减少内存占用。
  • 可重入性:同一个迭代器函数可以同时用于多个遍历(因为状态由外部传递,互不干扰)。

Lua 中的 ipairs(遍历数组)和 pairs(遍历表)都是无状态迭代器的典型应用,理解了这个逻辑,就能明白为什么泛型 for 能简洁地遍历各种集合了~

http://www.dtcms.com/a/541526.html

相关文章:

  • 社交网站 设计单仁营销网站的建设
  • RT-Thread FAL:为何NOR Flash必须注册为MTD设备?——深入解析RTOS设备模型
  • 如何查看网站蜘蛛数码公司网站建设的意义
  • 在婚恋网站做销售好吗网站推广排名哪家公司好
  • C#实现与欧姆龙PLC通信
  • 沧州瑞智网站建设一键优化下载安装
  • 网站源码带数据南充网站设计学校
  • 东莞高端品牌网站建设湛江网站建设托管
  • yolov5代码
  • wordpress首页文字广告框架在线seo
  • Rust:复合类型
  • Vue 3 + Element Plus 动态表格高度自适应方案详解
  • python flask简单使用
  • 课外辅导东莞网站建设技术支持saas系统是什么样的系统
  • 【论文精读】DeepSeek-OCR:探索视觉 - 文本压缩的新范式
  • 成都市网站设中国能源建设集团网站群
  • k8s 容器部署
  • Android的事件分发机制
  • 南京传销是以网站开发张槎网站建设
  • 写作网站好吗做游戏视频去哪个网站好
  • 斗兽棋象狮虎豹狼小游戏抖音快手微信小程序看广告流量主开源
  • MySQL的开始,MySQL的安装
  • 构建有记忆的 AI Agent:SQLite 存储 + 向量检索完整方案示例
  • 常州网站关键词优化咨询网站改版对网站优化影响最大的问题有哪些
  • 织梦(dedecms)怎么修改后台网站默认"织梦内容管理系统"标题邯郸seo排名
  • 知识图谱的知识工程建模:如何把名医的“诊断艺术”转化为辅助诊断系统
  • 图表设计网站临清网站推广
  • ubuntu22.04 ros2 fast_lio2 复现
  • 寻找长沙网站建设数据库网站开发
  • 做最好的win7系统下载网站织梦网站模板制作