Lua程序设计 无状态的迭代器

     无状态迭代器,就是一种自身不保存任何状态的迭代器,因此,我们可以在多个循环中使用同一个无状态的迭代器,避免创建新的closure。

     在每次迭代中,for循环都会用恒定状态和控制变量来调用迭代器函数。一个无状态的迭代器可以根据这两个值来为下次迭代生成下一个元素。典型例子:ipairs:迭代一个数组的所有元素。

a = {"one", "two", "three"}
for i, v in inpairs(a) do
  print(i, v)
end 
  迭代的状态就是需要遍历的table(一个恒定状态,它不会在循环中改变)及当前的索引值(控制变量)。ipairs(工厂)和迭代器可以在Lua中编写出来。
  local function iter (a, i)
    i = i + 1
   local v = a[i]
   if v then 
    return i, v
   end
   end
  
  function ipairs(a)
    return iter, a, 0
  end
   当Lua调用for循环中的ipairs(a)时,他会获得3个值:迭代器函数iter、恒定状态a和控制变量的初值0.然后Lua调用iter(a,0),得到1和a[1]。在第二次迭代中继续调用iter(a,1),得到2,a[2],一次类推,直至得到第一个nil为止。

     函数pairs与ipairs类似,也是用于遍历一个table中的所有元素。不同的是,它的迭代器函数是Lua中的一个基本函数next。

function pairs(t)
  return next, t, nil
end 
在调用next(t,k)时,k是table t的一个key。此调用会以table中的任意次序返回一组值:此table的下一个key及这个key所对应的值。而调用next(t, nil)时,返回table的第一组值。若没有下一组值,next返回nil。

for k , v in next,t do
 <loop body>
end

   Lua中会自动将for循环中表达式列表的结果调整为3个值。因此,上例中得到了next、t和nil。

   关于无状态迭代器的另一个例子(可以遍历列表的迭代器):

local function getnext( list , node)
 if not node then
   return list
 else
  return node.next
 end
end

function traverse (list)
 return getnext, list, nil
end
  这里将链表的头结点作为恒定状态(traverse返回的第二个值),而将当前节点作为控制变量。第一次调用迭代器函数getnext时,node为nil,因此函数返回list作为第一个结点。在后续调用中node不在为nil,此时迭代器会返回node.next.
 对于此迭代器的使用:
   list = nil
  for line in io.lines() do
  list = {val = line, next = list}  
  end
  
  for node in traverse(list) do
    print(node.val)
  end

你可能感兴趣的:(lua,程序设计无状态迭代器)