Lua笔记7-迭代器和泛型for

--[[ 7 迭代器与泛型for
-- 所谓迭代器就是一种可以遍历一种集合中所有元素的机制。在lua中,通常将迭代器表示为函数(例如:ipairspairs函数)。每调用一次函数,
-- 即返回集合中的下一个元素。一个closure结构通常涉及到两个函数:closure本身和一个用于创建该closure的工厂函数。
--  function values(t)
--      local i=0
--      return function() i=i+1 return t[i]  end
--  end
--
--  values就是一个工厂。每当调用这个工厂时,它就创建一个新的closure(即迭代器本身)。这个closure将它的状态保持在其外部变量ti中。每
--当调用这个迭代器时,它就从列表中返回下一个值。直到最后一个元素返回后,迭代器就会返回nil,以此表示迭代的结束。
--  while中使用这个迭代器:
--  t={10,20,30}
--  iter=values(t)      --创建迭代器,这个values返回的是一个匿名函数
--  while true do
--      local element=iter()    --调用迭代器,iter()匿名函数返回的则是:table中的元素的值。
--      if element == nil then break end
--      print(element)
--  end
--
--使用泛型for则更为简单。
--  t={10,20,30}
--  for element in values(t) do
--      print(element)
--  end
--使用到了 in 后面的作用域 表示元素的集合,一般是一个迭代器工厂函数。
--
--泛型for为一次迭代循环做了所有的薄记工作。它在内部保存了迭代器函数,因此不再需要iter变量。它在每次新迭代时调用迭代器,并在迭代器返回
--nil时结束循环。
--
--
-- ]]--


--[[ 7.2 泛型for的语义
--  泛型for在循环过程内部保存了迭代器函数。实际上它保存着3个值:一个迭代器函数,一个恒定状态和一个控制变量。泛型for语法:
--      for <var-list> in <exp-list> do
--          <body>
--      end
--
--  <var-list>是一个或多个变量名的列表,以逗号分隔;<exp-list>是一个或多个表达式的列表,同样以逗号分隔,通常表达式列表只有一个元素,
--即一句对迭代器工厂的调用。
--      for k,v in ipairs(t) do print(k,v) end
--k,v 是变量列表;表达式列表只有一个元素ipairs(t),ipairs是迭代器,foripairs的调用。
--
--
--for做的第一件事情是对in后面的表达式求值。这些表达式应该返回3个值供for保存:迭代器函数,恒定状态和控制变量的初值。在初始化步骤之后,
--for会以恒定状态和控制变量来调用迭代器函数。然后for将迭代器函数的返回值赋予变量列表中的变量。如果第一个返回值为nil。那么循环终止。否则
--for执行它的循环体,随后再次调用迭代器函数,并重复这个过程。
--
-- ]]--

--[[ 7.3 无效的迭代器
-- 所谓无状态的迭代器,正如其名所暗示的那样,就是一种自身不保存任何状态的迭代器。ipairs就是一个无状态的迭代器。
--  a={10,20,30}
--  for k,v in ipairs(a) do
--      print(k,v)
--  end
--
--  迭代的状态就是需要遍历的table(一个恒定状态,它不会在循环中改变)及当前的索引值(控制变量)。ipairs(工厂)和迭代器函数:
--
--
--
--local function myiter(a,i)
   i=i+1
   local v=a[i]
   if v then
      return i,v
   end
end

function myipairs(b)
   return myiter,b,0
end

T1={10,20,30}

for k,v in myipairs(T1) do     -- 存在一个疑问:myipairs()函数返回3个值,但是,为什么在for中调用的时候,myiter会自动的加载这2
   print(k,v)                 -- 返回的值呢?,这是for的功能,具体看下面的代码:
end


--下面的函数和for调用说明了,for的功能会自动将in 后面返回的值强制转换为3个值,并将它们应用到迭代器里面。

local function f1(a,b)
        return a+b
end

function g1(c)
        return f1,c,0
end


fx,m,n=g1(10)
print(m,n)

--print(fx()) --则会返回错误,因为这只是单纯的对myiter的调用,里面的参数a是没有值得。

for x in g1(10) do
        print(x)
        if x == 40 then
                break
        end
end
--
--
--
--
-- ]]--

--LUA调用for循环中的myipairs(T1)时,它会获得3个值:迭代器函数,myiter,恒定状态a和控制变量0。然后LUA调用myiter(T1,0),
--得到1T1[1].在第二次迭代中,继续调用myiter(T1,1),得到2T2[2],依次类推,直至得到第一个nil元素为止。

--[[ 函数pairsipairs类似,也是用于遍历一个table中的所有元素。不同的是,它的迭代器函数是LUA中的一个基本函数next
--      function pairst
--          return next,t,nil
--      end
--
--在调用next(t,k)时,ktable tkey。此调用会以table中的任意次序返回一组值:此table的下一个key,及这个key所对应的值。而调用
--next(t,nil)时,返回table的第一组值。若没有下一组值时,next返回nil
--有些用户喜欢不通过pairs调用而直接使用next
--  for k,v in next,t do
--      <loop body>
--  end


Lua 会自动将for循环中表达式列表的结果调整为3个值。上例中得到了nexttnil,这也正与调用pairs(t)的结果完全一致。

--LUA 中还可以将无状态的迭代器应用于 列表,详细可以查阅相关资料。
--
--
-- ]]--


--[[  7.4 具有复杂状态的迭代器
--
--   7.5 真正的迭代器
-- 以上两部分的内容详细可以查看资料。
-- ]]--


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值