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 脚本 我试图在其中使用十六进制数字 0x 如果我使用官方 Windows 二进制文件在控制台中运行此脚本 它可以正常工作 但是如果我在我的应用程序中运行它 简单的 dofile 我得到 malformed number n
  • 了解静态链接嵌入式lua环境中lua扩展dll的构建/加载

    我有一个相对复杂的 lua 环境 我试图了解以下内容如何工作 起始设置包括以下两个模块 主要应用 无lua环境 DLL 静态链接到lua lib 包括解释器 该 dll 被加载到主应用程序中 并运行 lua 控制台解释器和可从控制台访问的
  • Lua中如何获取目录列表

    我需要 LUA 中的目录列表 假设我的目录路径为 C Program Files 我需要该特定路径中所有文件夹的列表以及如何搜索该列表中的任何特定文件夹 Example 需要路径 C Program Files 中所有文件夹的列表 以下是上
  • 什么更快?循环或多个 if 条件

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

    我想保存游戏中创建的高分 并且当玩家点击高分按钮时可以在主菜单中看到 有人可以帮助我吗 您可以使用SQLITE https docs coronalabs com api library sqlite3 index html将高分保存到数据
  • 使用 corona sdk 验证电子邮件地址

    在我的项目中 有一个供用户填写详细信息的表单 其中有一个文本字段用于输入用户的电子邮件 ID 所以我需要在 corona 项目中验证该文本字段中的电子邮件 试试这个正则表达式 local email email protected cdn
  • lua http套接字超时

    LuaSocket HTTP 模块文档说可以在 HTTP 连接上设置超时 可以设置以下常量来控制 HTTP 模块的默认行为 PORT 用于连接的默认端口 PROXY 用于连接的默认代理 TIMEOUT 设置所有I O操作的超时时间 USER
  • lua_resume 的 from 参数的含义

    From Lua 5 2 参考手册 http www lua org manual 5 2 manual html lua resume int lua resume lua State L lua State from int nargs
  • 什么时候适合使用Lua这样的嵌入式脚本语言

    我玩 魔兽世界 大约有两年了 我对用来编写插件的 Lua 很好奇 由于到目前为止我读到的有关 Lua 的内容都是 快 轻 和 这太棒了 所以我想知道如何以及何时使用它 您需要在系统中嵌入像 Lua 这样的脚本语言的典型情况是什么 当您需要最
  • Kong - 验证上游 ssl(ssl_proxy 打开)

    我已经成功为 API 安装了 kong 网关 该 API 通过上游负载平衡到多个目标 应用程序服务器 现在 我有一个我的应用程序服务器的自签名证书 kong 和目标之间的 ssl 握手应该失败 我推断 kong 不验证上游证书 经过一些研究
  • 如何在Conky中实现一个基本的Lua功能?

    我正在尝试向我的 Conky 添加一个函数 该函数打印字符串的长度以用于调试目的 代码位于名为的文件内test lua 非常简单 function test word return string len word end 我这样加载它 在我
  • 尝试将 nil 与数字堆栈回溯进行比较?

    我正在通过以下链接玩 Lua https www lua org pil 4 2 html https www lua org pil 4 2 html并对某一点感到困惑 Lua 5 2 4 Copyright C 1994 2015 Lu
  • 为什么 LuaJIT 这么好?

    编辑 不幸的是 LuaJIT 已从下面链接的比较中删除 This 比较 http shootout alioth debian org u64 which programming languages are fastest php编程语言的
  • 使用 FastCGI 运行 Lua 脚本

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

    要么我太累了 要么我瞎了 我想学习 Lua 网络 因此我必须安装socketlib 所以我可以轻松地要求它 但我不知道我应该 要求 哪些文件 例子说 local socket require socket 但正如我所说 如果我使用 我不知道
  • 如何在 emacs lua-mode 中配置缩进?

    完整的 emacs 新手在这里 我在 Ubuntu 上使用 emacs 23 1 1emacs 入门套件 https github com technomancy emacs starter kit 我主要在 lua 模式下工作 安装了pa
  • 如何通过 C API 在自己的环境中执行不受信任的 Lua 文件

    我想通过调用在其自己的环境中执行不受信任的 lua 文件lua setfenv http pgl yoyo org luai i lua setfenv这样它就不会影响我的任何代码 该函数的文档仅解释了如何调用函数 而不解释如何执行文件 目
  • 在 Awesome-wm 中为特定应用程序设置窗口布局

    如何配置很棒 以便它可以启动两个窗口对齐的新应用程序 如下所示 xxxxxxxxxx xxxxxxxxxx xxxxxxxxxx xxxxxxxxxx 其中 x 是 pidgin 中的对话窗口 是好友列表窗口 一般来说 我想指定右窗口的宽度
  • 在 Lua/LuaFileSystem 中创建一个新文件

    我已经查看了 Lua 和 LuaFileSystem 文档 但尚未找到创建新文件的方法 我也在这里四处寻找 但目的相同 请注意 我正在寻找的解决方案必须与操作系统无关 以确保可移植性 但我很高兴针对不同的系统获得不同的答案 示例 将 Hel
  • 在循环内部或外部声明本地更好吗? [复制]

    这个问题在这里已经有答案了 我习惯这样做 do local a for i 1 1000000 do a

随机推荐

  • 如何在 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 类似对象 每次调用时都会返回序列中的下