首页 > 代码库 > Lua程序设计 迭代器与closure

Lua程序设计 迭代器与closure

          所谓“迭代器”就是一种可以遍历一种集合中所有元素的机制。在Lua中,通常将迭代器表示为函数。每调用一次函数,即返回集合中的“下一个”元素。

         每个迭代器都需要在每次成功调用之间保持一些状态,这样才能知道它所在的位置及如何步进到下一个位置。在Lua中,closure对于这类任务提供了极佳的支持,一个closure就是一种可以访问其外部嵌套环境中的局部变量的函数。对于closure而言,这些变量就可用于在成功调用之间保持状态值,从而使closure可以记住它在一次遍历中所在的位置。当然,为了创建一个新的closure,还必须创建它的这些“非局部的变量”。因此,一个closure通常涉及到两个函数:closure本身和一个用于创建该closure的工厂函数。

      示例:返回元素值的迭代器示例。

function values (table) 
  local i = 0
 return function () i = i + 1; return table[i] end
end
   本例中,values就是一个工厂,每当调用这个工厂时,它就创建一个新的closure(即迭代器本身)。这个closure将它的状态保存在其外部变量table和i中。
每当调用这个迭代器时,它就从列表table中返回下一个值。直到最后一个元素返回后,迭代器就会返回nil,以此表示迭代器结束。

       可以在while循环中使用这个迭代器:

  table = {1,2,3}
  iter = values (table)   --创建迭代器
  while true do
     local element = iter()   --调用迭代器
        if element == nil then break end
     print(element)
  end
 ================================= 
  然而,使用泛型for则更加简单
  table = {1,2,3}
   for element in values(table) do
     print(element)
   end
   
 泛型for为一次迭代循环做了所有的簿记工作。它在内部保存了迭代器函数,因此不再需要iter变量。它在每次新迭代时调用迭代器,并在迭代器返回nil时结束循环。

    示例:遍历当前输入文件中所有单词

  for word in allwords() do
    print()
  end
 对于迭代器,编写迭代器本身或许不容易,但使用它们却很容易。
 
 function allwords()
  local line = io.read()   -- 当前行
  local pos = 1            -- 一行中的当前位置。
   return function()       -- 迭代器函数
     while line do       --若为有效的行内容就进入循环。
         local s, e = string.find(line, "%w+" ,pos)
           if s then     --是否找到一个单词
             pos = s + 1 --该单词的下一个位置
             return string.sub(line, s, e)   --返回该单词
            else
               line = io.read() --没有找到单词,尝试下一行
               pos =1           --在第一个位置上,重新开始
            end
            end
           return  nil            -- 没有其余行了,遍历结束
      end
 end