If I write a generic walk
routine, why can I pass in my own iterators but not pairs
?
Here's a simple walk that does something for each item in src
.
function walk(src)
for n,i in src do
print(n, i[1]+i[#i]) end end
If I call this with walk(items(x))
then walk
works fine.
function items(lst, n)
n=0
return function()
if lst and n < #lst then
n=n+1
return n,lst[n] end end end
x={
{1,2},
{3,4},
{5,6},
{5,6}}
walk(items(x)) --> prints out (1,3),(2,7),(3,11),etc
But I try the same with pairs(x)
, I get a crash.
walk(pairs(x))
lua: x.lua: bad argument #1 to 'for iterator' (table expected, got nil)
stack traceback:
[C]: in function 'next'
x.lua:7: in function 'walk'
x.lua:31: in main chunk
[C]: in ?
So what is different about pairs
and my own iterator items
?
The pairs
function returns 3 values:
next
functionnil
The for-in
statement uses the 3 values in an equivalent process as follows:
local f, t, k = pairs(x)
local v
repeat
k, v = f(t, k)
if k then
-- for body
end
until not k
Since the 3rd value is always nil
, if you want the walk
function to be effective on pairs
, you need at least 2 arguments:
function walk(itor, t)
for n,i in itor, t do
print(n, i[1]+i[#i]) end end
You need 3 if you want it to be effective on any iterator functions.