Lua iterator and generic for

简介:
lua有两种循环的用法
1.  数字递增用法
> for i=1,10,3 do
>> print(i)
>> end
1
4
7
10


2. generic for用法
不写步长step则默认是1.
> t = {"hello","nihao",nil,"yes"}
> for k,v in ipairs(t) do
>>   print("k:" .. k .. " v:" .. v) 
>> end
k:1 v:hello
k:2 v:nihao

使用table.pack将...变量参数打包成sequence表以及n存储sequences个数.
> c = table.pack("he","hello",nil,"a ")
> for i=1, c.n do
print(c[i])
end
he
hello
nil
a

其他常用的generic for函数
Despite its apparent simplicity, the generic for is powerful. With proper
iterators, we can traverse almost anything in a readable fashion. The standard
libraries provide several iterators, which allow us to iterate over 
the lines of a file (io.lines), 
the pairs of a table (pairs), 
the entries of a sequence (ipairs), 
the words of a string (string.gmatch), 
and so on.

在没有generic for函数前的自定义循环用法, 使用factory 函数封装non-local变量和iterator函数(匿名函数), 多次调用iterator函数, 变更non-local变量的值来达到循环的目的. 例如 : 
> function factory(t)  -- 工厂函数, 返回一个匿名函数
>>   local i = 0  -- 封装一个本地变量
>>   return function () i = i+1; return t[i] end  把上层本地变量引入这个匿名函数(后面用它做循环)
>> end
> tbl = {10,20,30}
> iterator = factory(tbl)  -- 使用工厂函数生成一个循环函数
> while true do
>>   local element = iterator()
>>   if element == nil then break end
>>   print (element)
>> end
10
20
30


直接使用generic for : 
> for element in factory(tbl) do
>>   print (element)
>> end
10
20
30

generic for 的语法  : 
for <var-list> in <exp-list> do
  <body>
end

解释 : 
<var-list> 是1个或多个变量名, 逗号隔开, 不需要事先定义. 列表中的第一个变量为控制变量.
<exp-list> 是一个或多个表达式, 逗号隔开.
Lua处理generic for语法的方法和顺序.
1. 首先运行exp-list中的表达式, 把所有表达式的返回值转成3个返回值, 注意如果其中有返回多值的函数, 最后可能只用第一个返回值. 例如.
> function x(...) return ... end
> = x(1,2,3)
1       2       3
> =x(1,2,3),4
1       4
> a,b,c=x(1,2,3),4  -- 函数后面还有其他变量或表达式时, 取第一个返回值.
> = a,b,c
1       4       nil
> a,b,c = 4,x(1,2,3)  -- 函数在最后一位时, 返回多值
> = a,b,c
4       1       2
> a,b,c = 4,(x(1,2,3))  -- 函数外加括号, 强制取第一个返回值
> = a,b,c
4       1       nil

如果exp-list中有多个表达式, 则需要考虑以上情况, 不管怎么样, 第一次运行这些表达式的结果会转换成3个值, 多则废弃多的, 少则末尾以nil填补.
这三个值分别代表iterator function(使用_f表示), invariant state (使用_s表示) , initial value for the control variable (使用_var表示) .
2. 第二步则调用iterator函数, 并把结果赋予给var-list的各个变量.
var_1, ..., var_n = _f(_s, _var)
_var = var_1
然后判断var_1是否为nil, 如果为nil则退出循环, 如果不为nil则继续调用_f(_s, _var);
所以以下两种用法实际上是同样的效果 :
for var_1, ..., var_n in <exp-list> do <block> end

等同于
do 
local _f, _s, _var = <exp-list>
while true do
  local var_1, ..., var_n = _f(_s, _var)
  _var = var_1
  if _var == nil then break end
  <block>
  end
end

相关文章
|
7月前
|
定位技术
Collections.singletonMap()用法
Collections.singletonMap()用法
57 0
Collections.singletonList使用方法
Collections.singletonList使用方法
|
安全 容器
Collection和Collections的区别
Collection是一个接口,它是Set、List等容器的父接口;Collections是个一个工具类,提供了一系列的静态方法来辅助容器操作,这些方法包括对容器的搜索、排序、线程安全化等等。
1240 0
|
Java 容器 JavaScript
Collection Framework的Iterator实现
在比较HashMap和ConcurrentHashMap的不同之处发现了一个细节——关于Iterator的实现的不同,其实HashMap和ConcurrentHashMap还有更多不同的地方,这也是面试经常问到的问题,有一篇文章我觉得讲的很好了,Java进阶(六)从ConcurrentHashMap的演进看Java多线程核心技术。
921 0
|
iOS开发
'boost/iterator/iterator_adaptor.hpp' file not found之xcode生成时报错的解决方案
xcode生成rn(0.49.3)项目的时候出现“'boost/iterator/iterator_adaptor.hpp' file not found之xcode”报错。 原因:   /Users/xxx/.
1659 0