遍历用到的next函数的解析
举个遇到的例子
在用到泛型for的时候总会好奇next函数是如何被调用的,看到这里应该有了初步的了解,它是如何定义的呢?
其实上图中的函数调用格式应该是这样的:
next, table, state = pairs(table, state)
key, value = next(table, state)
官方解释:
next (table [, index])
Allows a program to traverse all fields of a table. Its first argument is a table and its second argument is an index in this table. next returns the next index of the table and its associated value. When called with nil as its second argument, next returns an initial index and its associated value. When called with the last index, or with nil in an empty table, next returns nil. If the second argument is absent, then it is interpreted as nil. In particular, you can use next(t) to check whether a table is empty.
The order in which the indices are enumerated is not specified, even for numeric indices. (To traverse a table in numeric order, use a numerical for or the ipairs function.)
The behavior of next is undefined if, during the traversal, you assign any value to a non-existent field in the table. You may however modify existing fields. In particular, you may clear existing fields。
我的翻译(个人翻译生硬,有错请明点):
可让程序遍历一个table的所有字段。它的第一个参数是table,第二个参数是一个table的索引。next()函数返回的是下一个元素索引(index)和其关联值(元素的value)。当nil作为函数被调用第二个参数时,next()函数返回最初的索引和其相关联的值。当用最后一个索引,或者用一个空表去调用next函数,next函数会返回nil。如果函数的第二个参数为缺省值,那么next函数的第二个参数会被解释为nil。其实,你可以利用next(t)去检查table是否为空。
穷举元素的顺序没有被指定,即便是数字的穷举。(如果你想按照数字的顺序去遍历一个table,可以用数值去指定(索引)或者ipairs函数)
如果在遍历过程中,你分配某些值给一个不存在的字段,抑或是修改一个现存字段,或者清理掉现存字段,这种next的行为并没有定义。
这里解释一下上图的工作原理:
第一次打印为nil,是因为pair函数返回的是一个next函数fun,一个恒定状态tb(表数据),一个初始值nil(该值的作用相当于表的索引,在还没有开始利用next函数时,初试值为nil是为了获取第一个索引值。)
第二次打印:根据上面对next函数的解析可知,图中的fun(即next函数)被调用后(此时的next值为nil,于是理应返回第一个元素的信息)返回第一元素的索引(1)和其想对应的值(true),根据多重赋值的原理,next值为重定向为1。
其余的打印:可结合上文理解。
简单说明一下泛型for的工作原理
假设有如下的for代码:
for key, value in Range(table) do
[deal]
end
PS:Range(table)是获取for遍历所需数据的函数,如ipairs()或pairs()函数。key,value合为控制变量。
首先那我们可以拿pairs函数作为Range()去理解,ipairs()和pairs()的官方描述如下:
ipairs (t) :
Returns three values: an iterator function, the table t, and 0, so that the construction
for i,v in ipairs(t) do body end
will iterate over the pairs (1,t[1]), (2,t[2]), ···, up to the first integer key absent from the table.
pairs (t) :
Returns three values: the next function, the table t, and nil, so that the construction
for k,v in pairs(t) do body end
will iterate over all key–value pairs of table t.
See function next for the caveats of modifying the table during its traversal.
这里就不做过多的翻译了,结合《Lua程序设计》7.2的内容分析:
For结构的处理流程(初学Lua,未深入底层实现,有错请明点):
(1)加载For结构遍历信息,即通过调用如ipairs()或pairs()函数,该函数返回有三个元素:next函数fun,恒定状态(即表数据)tb,控制变量的初值state,注意初值state为nil。
(2)调用next获取第一个元素的信息,For结构每次该改变控制遍历都需要调用next函数fun,获取第一元素值时也不例外。next函数fun需要两个参数:一个是恒定遍历tb,一个是控制变量的初始值state(获取第一个元素值前为nil),next函数fun如同下面的格式:
key, value = next(tb, state)
(解析next函数时有讲到)
调用完后,表示元素索引的key值被赋值为1,表示元素相关值的value值也同时被赋值为第一个元素的值。
(3)进行for结构的逻辑处理。
(4)再次调用获得下一个元素。此时原本的key被当作控制变量的初值被保存起来,然后调用next函数fun获取下一个元素值,key,value同时也被重定向。
反复重复(3)(4)步骤。
直到最后一个元素的key通过next函数被重定向为nill,for循环退出。

浙公网安备 33010602011771号