【问题标题】:Why this works in Lua? - for k, v in next, t, nil do print(k, v) end为什么这在 Lua 中有效? - for k, v in next, t, nil do print(k, v) end
【发布时间】:2017-07-07 09:47:47
【问题描述】:

我无法理解这个工作的 Lua 片段。

这个:

t = {'a', 'b', 'c'}
for k, v in next, t, nil do
  print(k, v)
end

返回这个:

1   a
2   b
3   c

谁能解释一下,

  • next 如何获取t 作为其参数?
  • t 如何成为for 的有效to 参数
  • 以及为什么需要 nil 并将其作为有效步骤接受?

【问题讨论】:

  • 接下来是 k (左边的数字索引)和 v 得到 t[k] (右边的值),其余的不知道
  • Lua 在执行generic "for" loop 时将t 作为next 的参数提供。这与数字“for”循环不同。
  • 是的,现在我明白了。这不是一个数字,而是一个泛型。 in next, t, nil 部分被评估为 next(t, nil) 现在突然变得有意义了......谢谢 Egor。
  • 你也可以完全忽略 nil:for k, v in next, t do print(k, v) end

标签: lua iterator next


【解决方案1】:

所有学分都归于Egor,因为他在 cmets 中的回答。

来自Lua 5.3 manual

类似的for语句

 for var_1, ···, var_n in explist do block end 

相当于代码:

 do
   local f, s, var = explist
   while true do
     local var_1, ···, var_n = f(s, var)
     if var_1 == nil then break end
     var = var_1
     block
   end
 end

因此原始语句转换为无限的while 循环,不断调用next(),初始参数为next(t, nil),并且在每次迭代中,第二个参数被t 表中的下一个索引替换。当最终next(t, index_n) 返回nil 时,循环中断。

在我看来,这似乎是一种非常强大的遍历表的方法,因为next() 几乎可以被任何可以完全控制迭代的函数所取代。哇。

【讨论】:

    【解决方案2】:

    扩展一下其他答案:

    “通用 for 循环”中涉及的值的更具描述性的命名如下:

    for k, v1, v2, … in f_step, state, k0 do  …  end
    

    它会像这样进入一个循环

    k,v1,v2,…=f_step(state,k0) ; if k==nil then break end ; k0=k ; --(…for body here…)
    k,v1,v2,…=f_step(state,k0) ; if k==nil then break end ; k0=k ; --(…for body here…)
    k,v1,v2,…=f_step(state,k0) ; if k==nil then break end ; k0=k ; --(…for body here…)
    …
    

    并且 f_step 可以随意修改state(尽管pairs/next 不这样做,作为另一个例子,string.gmatch 甚至忽略state k 完全将所有变化的状态保持在一个闭包中(如果你还不知道这个术语,请考虑“函数”)。)


    现在,pairs 所做的基本上只是

    function pairs( t )
        -- (__pairs logic goes here, omitted for brevity)
        return next, t, nil
    end
    

    和普通

    for k, v in pairs( t ) do  …  end
    

    基本上扩展为

    for k, v in next, t, nil do  …  end
    

    (除非t 有一个带有__pairs 的元表。)

    现在有两个原因可以显式写 next, t, nil 而不是 pairs - 以混淆尚不知道这一点的人,或避免触发 __pairs。 (为了避免触发__index/__newindex,你有rawget/rawset,为了避免__pairs,你明确写next, t, nil。或者你可以定义function rawpairs( t ) return next, t, nil end并使用它......)

    【讨论】:

      猜你喜欢
      • 2011-06-13
      • 1970-01-01
      • 1970-01-01
      • 2019-11-14
      • 2011-09-02
      • 2023-01-19
      • 2011-04-21
      • 2018-11-23
      • 2013-04-13
      相关资源
      最近更新 更多