You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将任意迭代器作为函数参数?为何自定义迭代器可用而pairs不行?

为何自定义walk函数能接收自定义迭代器,却无法传入pairs?

问题

我编写了一个通用的walk函数,为何可以传入自定义迭代器,却无法传入pairs?

示例

以下是一个简单的walk函数,用于处理src中的每个元素:

function walk(src)
  for n,i in src do 
    print(n,  i[1]+i[#i]) 
  end 
end

当用walk(items(x))调用时,函数运行正常:

function items(lst, n)
  n=0
  return function()
    if lst and n < #lst then
      n=n+1
      return n,lst[n] 
    end 
  end 
end

x={
  {1,2},
  {3,4},
  {5,6},
  {5,6}
}

walk(items(x)) --> 输出 (1,3),(2,7),(3,11)等

但尝试传入pairs(x)时,程序崩溃:

walk(pairs(x))

报错信息:

lua: x.lua: bad argument #1 to 'for iterator' (table expected, got nil)
stack traceback:
    [C]: in function 'next'
    x.lua:7: in function 'walk'
    x.lua:31: in main chunk
    [C]: in ?

核心区别:两类迭代器的返回格式不同

Lua的迭代器分为两类,你的items和pairs分属不同类型,而walk函数只适配了其中一种:

  1. 自定义items是闭包迭代器
    items函数返回的是一个单独的闭包函数,迭代所需的状态(列表lst和计数n)都保存在闭包内部。当for n,i in src执行时,Lua会直接重复调用这个闭包,每次调用返回下一组值,直到返回nil终止迭代。这种场景下,src只需要是一个函数,完全符合你walk函数的参数预期。

  2. pairs是无状态迭代器
    pairs实际上会返回三个值:迭代函数next、要遍历的目标表x、初始状态nil。Lua的for循环处理这类迭代器时,会自动拆解这三个值,每次调用next(x, 上一次的键)来获取下一组键值对。

但你的walk函数把pairs(x)的返回值直接当成单一的迭代函数传入for循环,导致Lua调用next时缺失了必需的表参数,因此触发“table expected, got nil”的报错。

修复walk函数的通用写法

要让walk同时支持两种迭代器,需要兼容Lua迭代器的标准返回格式(迭代函数、状态、初始值),修改后的代码如下:

function walk(iter, state, init)
  for n,i in iter, state, init do 
    print(n,  i[1]+i[#i]) 
  end 
end

修改后两种调用方式都能正常工作:

  • 闭包迭代器:walk(items(x))依然有效,Lua会将闭包作为iter,state和init默认设为nil,闭包本身不依赖这两个值。
  • 无状态迭代器:walk(pairs(x))可以正常运行,pairs(x)返回的三个值会被分别对应到iter、state、init参数,符合for循环的要求。

内容的提问来源于stack exchange,提问作者Tim Menzies

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 01:17:22