• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • vbs
  • DOS/BAT
  • hta/htc
  • python
  • perl
  • VBA
  • ColdFusion
  • ruby
  • PowerShell
  • Lua
  • Golang
  • linux shell
您的位置:首页 > 脚本语言 >Lua > 深入解读Lua中迭代器与泛型for的使用

深入解读Lua中迭代器与泛型for的使用

作者: 字体:[增加 减小] 来源:互联网

通过本文主要向大家介绍了lua如何实现面向对象,lua 面向对象,lua面向对象编程,面向对象构造函数,lua 对象等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

泛型for原理

迭代器是一种可以遍历集合中所有元素的机制,在Lua中通常将迭代器表示为函数,每调用一次函数,就返回集合中“下一个”元素。每个迭代器都需要在每次成功调用之间保持一些状态,这样才能知道它所在的位置及如何步进到下一个位置,closure就可以完成此项工作。下面的示例是列表的一个简单的迭代器:

function values(t)
 local i = 0
 return function() i = i + 1; return t[i] end
end

</div>

循环调用:

t = {10, 20, 30}
iter = values(t)
while true do
 local el = iter()
 if el == nil then break end
 print(el)
end
</div>

泛型for调用

for el in values(t) do print(el) end
</div>

泛型for为一次迭代循环做了所有的簿记工作。它在内部保存了迭代器函数,并在每次迭代时调用迭代器,在迭代器返回nil时结束循环。实际上泛型for保存了3个值:迭代器函数f、恒定状态s、控制变量a。for做的第一件事就是对in后面的表达式求值,并返回3个值供for保存;接着for会以s和a来调用f。在循环过程中控制变量的值依次为a1 = f(s, a0),a2 = f(s, a1),依次类推,直至ai为nil结束循环。

先看一段代码

for element in list_iter(t) do 
 print(element) 
end 
</div>

在不往下看之前,我们可以先试图根据我们已有的知识结构去理解这段代码。如果这样,list_iter(t)应该返回一个类似集合的东西,而我们已经知道实际上只返回了一个匿名函数,也就是迭代器。当然,每次调用迭代器都可以得到一个元素,迭代器的所有的结果倒是可以看成一个集合。因素齐了,我们需要一个逻辑上的解释,这个逻辑就是 泛型for的语义。
先看文法规定:

for <var-list> in <exp-list> do 
 <body> 
end 
</div>

整个过程是这样的:
首先,初始化,计算 in 后面表达式的值,表达式应该返回 泛型for 需要的三个值:迭代函数、状态常量、控制变量;与多值赋值一样,如果表达式返回的结果个数不足三个会自

动用nil 补足,多出部分会被忽略。
第二,将状态常量和控制变量作为参数调用迭代函数(注意:对于 for 结构来说,状态常量没有用处,仅仅在初始化时获取他的值并传递给迭代函数)。

第三,将迭代函数返回的值赋给变量列表。
第四,如果返回的第一个值为 nil 循环结束,否则执行循环体。
第五,回到第二步再次调用迭代函数。

更具体地说:

for var_1, ..., var_n in explist do block end 
</div>

等价于

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 
</div>

 泛型 for 在自己内部保存三个值:迭代函数、状态常量、控制变量。

迭代器的状态

无状态的迭代器本身不保存任何状态,for循环只会用恒定状态和控制变量来调用迭代器函数。这类迭代器典型例子就是ipairs,下面是ipairs的Lua实现:

local function iter(s, i)
 i = i + 1
 local v = s[i]
 if v then return i, v end
end
function ipairs(s)
 return iter, s, 0
end
</div>

当for循环调用ipairs(list)时,会获得3个值,然后Lua调用iter(list, 0)得到list, list[1],调用iter(list, 1)得到list, list[2],知道得到一个nil为止。

虽然泛型for只提供一个恒定状态和一个控制变量用于状态的保存,但有时需要保存许多其他状态。这时可以用closure来保存,或者将所需的状态打包为一个table,并保存在恒定状态中。

闭包、迭代器和泛型for

到现在,Lua为我们准备了三块积木:闭包、泛型for和迭代器。一个循环,我们可以利用闭包+迭代器,也可以使用泛型for+迭代器。那我们该怎么取舍呢?Lua也给出了建

议。

function iter (a, i) 
 i = i + 1 
 local v = a[i] 
 if v then 
  return i, v 
 end 
end 
 
function ipairs (a) 
 return iter, a, 0 
end 
 
for i, v in ipairs(a) do 
 print(i, v) 
end 
</div>

这种情况是Lua最推荐的,迭代器不依赖upvalue,不产生闭包,状态常量和控制变量借助泛型for保存,通过迭代器的参数传递给了迭代器。
再给一个书中的例子:

local iterator -- to be defined later 
 
function allwords() 
 local state = {line = io.read(), pos = 1} 
 return iterator, state 
end 
 
function iterator (state) 
 while state.line do -- repeat while there are lines 
  -- search for next word 
  local s, e = string.find(state.line, "%w+", state.pos) 
  if s then -- found a word? 
   -- update next position (after this word) 
   state.pos = e + 1 
   return string.sub(state.line, s, e) 
  else -- word not found 
   state.line = io.read() -- try next line... 
   state.pos = 1 -- ... from first position 
  end 
 end 
 return nil -- no more lines: end loop 
end 

</div>

这样好不好呢,Lua给的答案是否定的。书中有一段话说得很清楚:
我们应该尽可能的写无状态的迭代器,因为这样循环的时候由for 来保存状态,不需要创建对象花费的代价小;如果不能用无状态的迭代器实现,应尽可能使用闭包;尽可能不

要使用table 这种方式,因为创建闭包的代价要比创建table 小,另外Lua 处理闭包要比处理table 速度快些。

</div>

您可能想查找下面的文章:

  • 深入解读Lua中迭代器与泛型for的使用
  • Lua中函数与面向对象编程的基础知识整理
  • Lua编程示例(二):面向对象、metatable对表进行扩展
  • Lua教程(十三):弱引用table
  • Lua面向对象编程之类的简单实现方式
  • lua+love2d制作的2048游戏
  • lua实现的2048小游戏
  • Lua模拟面向对象示例分享
  • Lua中实现面向对象的一种漂亮解决方案
  • Lua中让回调函数支持回调对象方法的解决方法

相关文章

  • Lua教程(十四):字符串库详解
  • Lua中调用C语言函数实例
  • Openresty服务器使用lua脚本写的Hello World简单实例
  • Cocos2d-x中调用Lua及HelloWorld.lua源码分解
  • Lua判断一个目录或文件是否存在的方法
  • 获取Lua表结构(table)数据实例
  • Lua教程(十六):系统库(os库)
  • Lua中table的几种构造方式详解
  • Lua学习笔记之函数、变长参数、closure(闭包)、select等
  • Lua变量类型简明总结

文章分类

  • vbs
  • DOS/BAT
  • hta/htc
  • python
  • perl
  • VBA
  • ColdFusion
  • ruby
  • PowerShell
  • Lua
  • Golang
  • linux shell

最近更新的内容

    • Lua获取网络时间(获取时间同步服务器的时间)
    • Lua面向对象之多重继承、私密性详解
    • Lua判断Table是否为空的方法(空的table即{})
    • Lua编程中的一些基本语法整理
    • Lua中让回调函数支持回调对象方法的解决方法
    • lua+love2d制作的2048游戏
    • Lua中table的几种构造方式详解
    • Lua学习笔记之类型与值
    • Lua教程(三):表达式和语句
    • Lua脚本获取喜马拉雅MP3音频地址

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有