Lua中有状态迭代器和无状态迭代器的区别

2024-05-21

Lua中无状态和有状态迭代器有什么区别,请详细解释一下?什么时候需要使用无状态,什么时候需要使用另一种?我需要例子来理解这个概念。


首先让我们就一个定义达成一致:(在 Lua 中)迭代器是function-类似对象,每次调用时都会返回序列中的下一个值。我认为重写有帮助for迭代完成是Lua参考手册:

for itemlist in expression do block end

逻辑上等价于(伪代码):

do
    local func, seq, controlVar = expression
    while true do
        local itemlist = func(seq, controlVar)
        if first of itemlist == nil then break end
        controlVar = first of itemlist

        block (which uses items in itemlist)
   end
end

where expression是数据的三元组(或返回这样的三元组的函数调用):

  • func是实际的迭代器函数
  • seq是被迭代的序列
  • controlVar是循环控制变量

迭代状态是在迭代序列中查找下一项所需的任何状态。因此,无状态迭代器是这样一种迭代器:func不包含任何此类状态:您可以调用func(seq, controlVar)在任何时候,返回值总是相同的(如果 seq 没有​​改变);它不取决于通话之前发生的事情。

如上所示,Lua支持one循环控制变量。因此,为了使序列能够通过无状态迭代器进行迭代,必须能够根据以下条件确定序列中的下一项:one循环控制变量。即,必须能够仅从“(s,controlVar)”中找出“下一个项目”。这ipairs()生成一个迭代器来执行以下操作:ipairs(s)返回三元组(iterFunction, s, 0); the iterFunction可以给予s和索引 0,并返回1, s[1], then 2, s[2]等等(最终对于包含 N 个项目的表来说什么也没有)。

如果查找序列中的下一项需要多个循环控制变量怎么办?或者取决于其他变量的状态,哪些变量应该在迭代期间保存?例子:

  • 无限迭代器可能需要跟踪“第一个”项目,以便一旦到达序列末尾,它就可以从第一个项目恢复;
  • 图迭代器可能需要在深度优先搜索中跟踪“最近的同级”,以便一旦到达分支的末尾,它就可以继续搜索下一个最近的同级。

有状态迭代器保存有关迭代的状态,以便可以找到下一项。在 Lua 中,如果迭代器函数是一个闭包(具有上值的函数)或函子(一个表现为函数的表,即具有一个__call元方法)。向上值(闭包)或数据成员(函子)可以存储所需的状态。

无状态迭代器始终可以包装到有状态迭代器中。为了ipairs:

function statefulIpairs(s)
    local f, s, var = ipairs(s)
    return function() 
        local i, v = f(s,var)
        var = i
        return i, v
    end
end

这可以称为

tbl = {'a', 'b', 'c', 'd'}
sip = statefulIpairs(tbl) -- sip is stateful iter specific to tbl
for i,v in sip() do print(i,v) end

有状态迭代器的开发人员决定迭代器具有哪些功能:迭代器的 API 可能允许倒回、反转方向或其他操作。这在闭包的情况下甚至是可能的:可以使用附加参数来访问附加功能。例如,接受第三个参数,当该参数非 nil 时,将重置为序列的开头:

function resetableStatefulIpairs(s)
    local f, s, var = ipairs(s)
    local start = var
    return function(a,b,reset)
        if reset ~= nil then var = start; return end        
        local i, v = f(s,var)
        var = i
        return i, v
    end
end

sip = resetableStatefulIpairs(tbl) -- sip is stateful iter specific to tbl
for i,v in sip() do print(i,v) end
sip(nil, nil, true) -- reset it
for i,v in sip() do print(i,v) end

Update一个更简洁的示例是如何生成一个接受命令的函数迭代器,以便您可以“...停止序列中的任何位置并迭代序列的其余部分 3 次”(按照 @deduplicator 的要求):

function iterGen(seq, start)
    local cvar = start or 1
    return function(cmd) 
        if cmd == nil then
            if cvar > #seq then return nil, nil end
            val = seq[cvar]
            cvar = cvar + 1
            return cvar-1, val

        else
            cmd = cmd[1]
            if cmd == 'rewind' then
                cvar = start or 1

            elseif cmd == 'newstart' then
                start = cvar
            end
        end
    end
end

与上述:

> s = {1,2,3,4,5,6,7}
> iter = iterGen(s)
> for i,v in iter do print(i,v); if i==3 then break end  end
1       1
2       2
3       3
> iter {'newstart'} -- save current as the new start pos
> for i,v in iter do print(i,v)  end -- continue till end
4       4
5       5
6       6
7       7
> iter {'rewind'}
> for i,v in iter do print(i,v)  end
4       4
5       5
6       6
7       7
> iter {'rewind'}
> for i,v in iter do print(i,v)  end
4       4
5       5
6       6
7       7

正如所演示的,有状态迭代器没有什么特别之处,除了迭代状态位于迭代器内部这一事实之外,因此如上所述,开发人员需要公开所需的功能,例如上面的倒带和新开始。对于无状态迭代器,没有限制。

将迭代器设计为仿函数将是一个更自然的 API,因为这样迭代器“函数”就有了可以调用的“方法”,但创建一个可命令的函数是一个有趣的挑战。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Lua中有状态迭代器和无状态迭代器的区别 的相关文章

  • 了解静态链接嵌入式lua环境中lua扩展dll的构建/加载

    我有一个相对复杂的 lua 环境 我试图了解以下内容如何工作 起始设置包括以下两个模块 主要应用 无lua环境 DLL 静态链接到lua lib 包括解释器 该 dll 被加载到主应用程序中 并运行 lua 控制台解释器和可从控制台访问的
  • 什么更快?循环或多个 if 条件

    我想知道什么更快 是只用一条指令 即 1 1 执行 9 次 for 循环还是执行 9 个 if 条件时 我认为 if 更快 因为您不需要检查循环中的指令 它应该几乎相同 因为for循环本质上是检查if条件为真并运行一段代码 非常类似于if声
  • 我应该用 C++ 封装 Lua 代码的哪些代码?

    我终于将 LuaBind 配置为与我的 C 项目一起使用 我最近发现 Tiled 地图编辑器可以选择将文件导出为 lua 所以我想尝试一下 我将使用什么代码来封装下面粘贴的代码以使其与我的 C RPG 项目一起使用 return versi
  • 在 Corona sdk 上保存高分?

    我想保存游戏中创建的高分 并且当玩家点击高分按钮时可以在主菜单中看到 有人可以帮助我吗 您可以使用SQLITE https docs coronalabs com api library sqlite3 index html将高分保存到数据
  • Lua-迭代嵌套表

    我已经学习 Lua 几个星期了 这一次又一次成为我的症结所在 我尝试阅读有关该主题的帖子和书籍 我使用 Lua 查询软件监控系统 Nimsoft 我的数据以表格形式返回给我 我不会发布整个输出 但这里有一个我认为可以描述结构的片段 表参考是
  • Lua :: 如何编写加载多个CPU的简单程序?

    我还无法用 Lua 编写一个可以加载多个 CPU 的程序 自从Lua通过协程支持这个概念 http www lua org pil 9 4 html 我相信这是可以实现的 我失败的原因可能是以下之一 这在Lua中是不可能的 我写不出来 an
  • 使用 FastCGI 运行 Lua 脚本

    我目前正在尝试找出使用 FastCGI 与 lighttpd 或 Nginx 一起运行 Lua 脚本的方法 我唯一能挖到的是WSAPI http keplerproject github com wsapi 开普勒计划的一部分 但我想知道是
  • VB6 - Lua 集成

    我想知道是否有人有任何集成 Lua 和 VB6 的技巧 我正在运行一个小型在线角色扮演游戏 添加一些脚本会很棒 嗯 这是可行的 我曾经为 Lua 5 0 2 做过 但找不到文件 在您拥有的选项中 您可以 将 Lua 封装在公开 Lua AP
  • 检查多个位置的值并仅在源唯一时返回匹配项

    假设我有一个清单Vendors 阿斯达 乐购 Spar 我有一个清单Sources 或者这个类比中的供应商 家乐氏 Kellogg 吉百利 Cadbury 雀巢 Nestle 强生 Johnsons 帮宝适 Pampers Simple 等
  • 如何在我的 Lua 脚本中添加“睡眠”或“等待”?

    我正在尝试通过更改一天中的时间来为游戏制作一个简单的脚本 但我想快速完成 这就是我要说的 function disco hour minute setTime 1 0 SLEEP setTime 2 0 SLEEP setTime 3 0
  • Openresty 中的并发模型是什么?

    我很难理解 openresty 或 nginx 的并发模型 我读了Lua变量作用域 http wiki nginx org HttpLuaModule Lua Variable Scope 它解释了变量的生命周期 但它没有说明对它们的并发访
  • LuaJ 导入 Lua 方法

    我正在使用 LuaJ 并且我有一个 lua文件充满了一堆函数 如何通过 LuaJ 导入这些函数以在 Java 中使用 一种选择是将文件编译为 Java 代码并导入它 另一种方法是使用可嵌入解释器直接从 Java 代码中调用 Lua 文件 E
  • 如何让我的 add 命令找到第一个变量和第二个变量的值,然后将它们加在一起?

    vars values function open file lex file end function lex file local data io open file r for char in data lines do Print
  • Lua中有状态迭代器和无状态迭代器的区别

    Lua中无状态和有状态迭代器有什么区别 请详细解释一下 什么时候需要使用无状态 什么时候需要使用另一种 我需要例子来理解这个概念 首先让我们就一个定义达成一致 在 Lua 中 迭代器是function 类似对象 每次调用时都会返回序列中的下
  • SHA2 512 的改编给出了不正确的结果

    我正在尝试调整 SecureHashAlgorithm 的纯 Lua 实现here http lua users org wiki SecureHashAlgorithm对于 SHA2 512 而不是 SHA2 256 当我尝试使用改编时
  • 在 Lua 中只归档一次

    我想知道是否有一种方法可以只执行一次 lua 文件 并且后续尝试执行该 lua 文件将导致无操作 我已经考虑过做一些类似于 C header 的 if else endif 技巧的事情 我想知道是否有一个标准方法来实现这一点 James w
  • Lua表在内存中是如何处理的?

    lua如何处理表的增长 是否相当于ArrayList在Java中 IE 需要连续的内存空间 并且当它变得大于已经分配的空间时 内部数组被复制到另一个内存空间 有什么聪明的方法来引导吗 我的问题是 表是如何存储在内存中的 我不是问如何在 Lu
  • 表长度运算符的性能

    卢阿有 运算符来计算用作数组的表的 长度 在诸如 C 之类的语言中 计算出某个内容的长度后 通常不会再次计算它 例如int len strlen string 这在 Lua 中有什么不同吗 其中一个的效率是否比另一个低 显然这可能不会显示显
  • 从命令行运行 vlc 扩展

    我有一个用 Lua 编写的 vlc 扩展 我知道如何从 GUI 运行它 查看 gt 我的扩展 我想从命令行运行它 这样我就不需要每次都启动X 它还没有实施 查看门票 3883 https trac videolan org vlc tick
  • 将值存储在 lua 的 userdata 对象中

    我想做的是这样的 object foo bar print object foo 其中 对象 是用户数据 我已经用谷歌搜索了一段时间 使用关键字 newindex 和 lua rawset 但我找不到任何可以实现我想要的功能的示例 我想用

随机推荐

  • 如何在 2 个项目之间移动 Google Cloud DNS 条目?

    我想做一些非常简单的事情 但看起来几乎不可能做到 我的 Google Cloud DNS 帐户中有不同的项目 我想将一些条目 域 从一个项目移动 迁移 到另一个项目 我不想走删除 重新创建路径 因为所有域都是活动的 并且我不希望有任何停机时
  • 防止在派生类中调用基类实现的接口方法 C#

    是否可以在基类中实现接口并允许在第一个派生类级别调用 覆盖已实现的方法 但阻止从任何进一步的派生类调用它 public interface IInterfaceSample bool Test public class Base IInte
  • 如何在Django中显示内存中的图片?

    我知道如何将图片显示为内存中的页面 如下所示 import cStringIO mStream cStringIO StringIO picBin return HttpResponse mStream getvalue image jpg
  • Chrome 问题:“无法加载资源:net::ERR_CONNECTION_TIMED_OUT”

    我尝试通过 HTTPS 访问我的 Web 应用程序 它无法加载 JavaScript 文件并显示 无法加载资源 net ERR CONNECTION TIMED OUT 但它在 IE 和 Firefox 中按预期工作 通过 HTTP 在 C
  • 就SQL注入而言,哪种sql查询更安全

    我有两个 SQL 查询正在尝试更新sup and opp每次调用查询时 值分别为 1 和 1 第一个查询 query update disc set sup sup opp opp where did did int sup getnoof
  • SVG img keepAspectRatio Chrome

    当我对 SVG 文件中的图像使用preserveAspectRatio none 时 它 似乎在 Google Chrome 中不起作用 SVG 不会根据图像宽度和高度进行缩放
  • 右下角对齐的更好方法

    有没有更好的方法来对齐单元格右下角的某些内容 我有一个 div 只包含一个背景图像 10px x 10px 我使用以下样式将其放在右下角 我所在的单元格高 40 像素 这样做会导致我失去 div 上方的 30px 我还使用它作为单击的对象
  • SQL Server - 选择满足条件的第一行

    我有 2 个包含 ID 的表 其中一个表中会有重复的 ID 我只想为表 B 中的每个匹配 ID 返回一行 例如 Table A objectIdA objectIdB 1 A 1 B 1 D 5 F Table B objectIdA 1
  • MSysGit 与 Windows 版 Git

    我无法确定MSysGit 和 Windows 版 Git 之间的区别 http msysgit github com 它们有何不同 为什么我会选择其中之一而不是另一个 它们不是同一个东西吗 On http msysgit github co
  • 如何解析cURL返回的header?

    我正在尝试使用 cURL 与 API 进行通信 其中一种方法要求我传递ININ ICWS CSRF Token标题 即WAhtYWxoYXlla1dBY2NvUkRJWCQxZmUxZWFhZS0xZTE0LTQyNGYtYjdhZS0zN
  • Ios Swift制作字体切换粗体、斜体、boldItalic、正常而不改变其他属性

    我很惊讶 在 Swift 中简单地为现有字体设置粗体和斜体是如此复杂 我只是想通过在字体类上使用以下方法来简化事情 我希望将以下方法添加到已设置字体系列和字体大小的现有字体中 我需要保留这些并仅更改以下内容 setBold Shud 保留斜
  • 如何强制 pm2 在特定时间后重新启动?

    我在用PM2让我的 Node js 应用程序保持运行 有什么办法可以拥有PM2每 1 小时重新启动一次我的应用程序 将下面的代码放入pm2 js并开始它pm2 start pm2 js var pm2 require pm2 pm2 con
  • 共享辅助轴

    如何使用 matplotlib 中的子图设置共享辅助轴 这是显示问题的最少代码 import numpy as np import matplotlib as mpl import matplotlib pyplot as plt def
  • 如何将包含大量表格的 HTML 文档转换为 Word 文档?

    我创建了一个包含许多表格的 HTML 文档 如何将文档转换为Word 问题是 如果我用 Word 打开 HTML 文档 由于某种原因我会得到非标准的双行表格 table border 1 color 000000 cellpadding 0
  • 由于缺少 PHP 扩展,CakePHP 3 无法连接到数据库

    我正在尝试使用 WT NMP 安装 cakePHP 3 0 0 但收到以下消息 CakePHP 无法连接到数据库 由于以下原因无法使用数据库驱动程序 Cake Database Driver Mysql 缺少 PHP 扩展或未满足的依赖项
  • 如何让 Vim 突出显示非 ascii 字符?

    我试图让 Vim 突出显示非 ASCII 字符 是否有可用的设置 正则表达式搜索模式或插件来执行此操作 在 a 中使用范围 搜索中的字符类 您应该能够excludeASCII 十六进制字符范围 因此突出显示 假设您有hlsearch启用 所
  • 依赖解析算法

    我正在编写一个包管理器 为此我希望依赖项解析尽可能强大 每个包都有一个版本列表 每个版本包含以下信息 具有可比性的 ID 依赖关系 软件包列表以及每个软件包的一组可接受的版本 冲突 软件包列表以及每个软件包的一组与该版本一起导致问题的版本
  • 查看寻呼机 - 使用静态变量以编程方式滑动到下一页

    我想在我的 ViewPager 中以编程方式制作幻灯片 我的问题是 滑动事件是由放置在 ViewPager 保存的片段内部的按钮调用的 我知道代码 viewpager setCurrentItem int index 现在我的想法是使 Vi
  • 将用户定义的表类型从 VBA 传递到 SQL

    我的任务是创建一个 Excel 电子表格作为 SQL 数据库的前端 以及一些对数据执行复杂计算的 C 我的老板想要前端作为电子表格 而计算对于 VBA 来说似乎太复杂了 目前 检索数据集的存储过程运行良好 然后 用户将在 Excel 中编辑
  • Lua中有状态迭代器和无状态迭代器的区别

    Lua中无状态和有状态迭代器有什么区别 请详细解释一下 什么时候需要使用无状态 什么时候需要使用另一种 我需要例子来理解这个概念 首先让我们就一个定义达成一致 在 Lua 中 迭代器是function 类似对象 每次调用时都会返回序列中的下