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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值