zoukankan      html  css  js  c++  java
  • [Lua] 迭代器 闭合函数 与 泛型for

    首先看看一下闭合函数(closure),见如下代码:

     1 function newCounter()
     2     local i = 0       -- 非局部变量(non-local variable)
     3     return  function ()  -- 闭合函数(closure)
     4                 i = i + 1
     5                 return i
     6             end
     7 end
     8 
     9 c1 = newCounter()
    10 print(c1()) -- 1
    11 print(c1()) -- 2
    12 
    13 c2 = newCounter()
    14 print(c2()) --1
    15 print(c1()) --3
    16 print(c2()) --2

    闭合函数可以用来实现迭代器(iterator)(迭代器用来遍历集合,每调用一次函数,即返回集合中的下一个元素)。

    例如:遍历一个table的时候,我们经常使用如下方式。

    1 t = {'x', 'y', 'z'}
    2 for k, v in ipairs(t) do
    3     print(k .. " " .. v)
    4 end
    5 -- 打印结果
    6 -- 1 x
    7 -- 2 y
    8 -- 3 z

    我们可以用while遍历集合,也可以用for,并且用for会容易很多,下面看一下for的语义:

     1 -- A for statement like
     2 
     3      for var_1, ···, var_n in explist do block end
     4 -- is equivalent to the code:
     5 
     6      do
     7        local f, s, var = explist
     8        while true do
     9          local var_1, ···, var_n = f(s, var)
    10          var = var_1
    11          if var == nil then break end
    12          block
    13        end
    14      end
    15 -- Note the following:
    16 
    17 -- explist is evaluated only once. Its results are an iterator function, a state, and an initial value for the first iterator variable.
    18 -- f, s, and var are invisible variables. The names are here for explanatory purposes only.
    19 -- You can use break to exit a for loop.
    20 -- The loop variables var_i are local to the loop; you cannot use their values after the for ends. If you need these values, then assign them to other variables before breaking or exiting the loop.

    注:

    1 for做的第一件事就是对in后面的表达式求值,这些表达式应该返回3个值供for保存:迭代器函数(f)、恒定状态(s)、控制变量的初值(var),不足的值用nil补足。

    2 在初始化之后,for会以恒定状态s和控制变量var来调用迭代函数f,然后for将迭代起的返回值赋予变量列表中的变量(var_1, var_2 ..., var_n),其中var_1称为控制变量,当返回的var_1为nil时,循环终止。

    下面是书中的Lua实现ipair的例子:

     1 t3 = {"x", "y", "z"}
     2 
     3 local function iter (a, i)
     4     i = i + 1
     5     local v = a[i]
     6     if v then
     7         return i, v    -- 第一个返回值是控制变量
     8     end
     9 end
    10 
    11 function __ipairs (a)
    12     return iter, a, 0  -- 3个值,迭代器、恒定状态、控制变量。 第一次是iter(a, 0),之后则是iter(a, i)
    13 end
    14 
    15 for i, v in __ipairs(t3) do
    16     print(i .. " " .. v)
    17 end
    18 
    19 -- 输出结果:
    20 -- 1 x
    21 -- 2 y
    22 -- 3 z

    结合上面for的语义表达式,来分析上面这段代码,__ipairs是一个工厂,生产迭代器iter,迭代器的初始参数是a和0,即恒定状态(a)和控制变量(i),iter的返回值是控制变量i和返回值a[i]。

    pairs与ipairs类似,但key是无序的,它的迭代器函数是 Lua中的一个基本函数next,在调用next(t, k)时,k是table t的一个key,此调用会以table中的任意次序返回一组值,而调用next(t, nil)时,返回table的第一组值。若没有下一组值的时候,next返回nil。

    1 function pairs(t)
    2     return next, t, nil
    3 end

    也可以直接使用next:

    1 for k, v in next, t do
    2     <loop body>
    3 end
  • 相关阅读:
    手机键盘
    关于大数除法
    整数转字符串,字符串转整数
    动态规划习题:数字三角形(01背包)
    关于最长不重复子串的问题
    Ubuntu12.04 下vim的使用(不断更新)
    Ubuntu12.04 如何设置环境变量
    LeetCode--Reverse Linked List II
    Ubuntu12.04 使用svn如何设置代理
    July面试整理系列--(5)
  • 原文地址:https://www.cnblogs.com/p0e0o0p0l0e0/p/8485893.html
Copyright © 2011-2022 走看看