lua有两种循环的用法
1. 数字递增用法
2. generic for用法
> for i=1,10,3 do
>> print(i)
>> end
1
4
7
10
2. generic for用法
不写步长step则默认是1.
使用table.pack将...变量参数打包成sequence表以及n存储sequences个数.
其他常用的generic for函数
在没有generic for函数前的自定义循环用法, 使用factory 函数封装non-local变量和iterator函数(匿名函数), 多次调用iterator函数, 变更non-local变量的值来达到循环的目的. 例如 :
直接使用generic for :
generic for 的语法 :
> 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