可变数量的函数参数Lua 5.1

Fro*_*rog 21 lua

在我的Lua脚本中,我正在尝试使用可变数量的参数创建一个函数.据我所知它应该像下面这样工作,但不知怎的,我在TI-NSpire上得到了Lua 5.1的错误(全局arg是零).我究竟做错了什么?谢谢!

function equation:init(...)
    self.equation = arg[1]
    self.answers = {}
    self.pipe = {arg[1]}
    self.selected = 1

    -- Loop arguments to add answers.
    for i = 2, #arg do
        table.insert(self.answers, arg[i])
    end
end

instance = equation({"x^2+8=12", -4, 4})
Run Code Online (Sandbox Code Playgroud)

RBe*_*eig 36

路易斯的答案是正确的,如果比语言的初学者更苛刻可能希望.我会尝试详细说明一下,希望不会造成额外的混乱.

您的问题是在嵌入TI计算器特定模型中的Lua环境中.因此,将会有与独立Lua不同的细节,但大多数细节将与您的环境中可用的库和函数相关.Lua的嵌入式版本与其作者分发的独立Lua有很大不同,这是不寻常的(虽然因为Lua是开源的,可能).(Lua Binaries是许多平台的二进制文件库.Lua for Windows是一个包含电池的Windows完整发行版.)

您的示例代码具有一个混淆因素,它需要与计算器框架提供的类系统接口所需的详细信息.该细节主要表现为您的equation对象与equation:init()被调用函数之间缺少连接.由于有一些技术可以粘合它,这只是一种分心.

正如我所理解的那样,你的问题可归结为关于如何在Lua中声明和实现可变函数(具有可变数量的参数的函数)的混淆.根据你对路易斯答案的评论,你一直在阅读Lua编程的网络版(又名PiL).你引用了第5.2节.PiL是该语言背景的良好来源.不幸的是,可变函数是一直在变化的特征之一.从Lua 5.0版起,本书的在线版本是正确的,但TI计算器可能正在运行Lua 5.1.4.

在Lua 5中,使用参数列表声明可变参数函数,该参数列表以...代表其余参数的符号结束.在Lua 5.0中,调用是使用一个名为"magic"的局部变量实现的,该变量arg包含一个包含与之匹配的参数的表....这要求每个可变参数函数在调用时创建一个表,这是垃圾收集器不必要的开销和压力的来源.所以在Lua 5.1中,实现发生了变化:...可以直接在被调用函数中用作匹配参数的别名,但实际上并没有创建表.相反,如果需要参数计数,则编写select("#",...),如果需要第n个参数的值,则编写select(n,...).

您的示例中的混淆因素会返回到类系统.您想声明该功能equation:init(...).由于此声明使用冒号语法,因此它等同于写入equation.init(self,...).因此,当最终通过类框架使用元方法__call调用时,真正的第一个参数被命名self,零个或多个实际参数将匹配....

正如下面Amr的评论所指出的那样,表达式select(n,...)实际上返回了第n个参数的所有值,这在构造的情况下特别有用self.answers,但也导致了初始化中可能存在的错误self.pipe.

以下是我在您的定义中尝试实现的修正近似值equation:init(),但请注意我手边没有TI计算器,这是未经测试的:

function equation:init(...)
    self.equation = select(1, ...)
    self.pipe = { (select(1,...)) }
    self.selected = 1
    self.answers = { select(2,...) }
end
Run Code Online (Sandbox Code Playgroud)

在上面显示的修订版本中,我编写{(select(1,...))}了一个表,其中只包含一个元素,这是第一个参数,并{select(2,...)}创建一个包含所有剩余参数的表.虽然以这种方式可以插入表中的值的数量有限,但该限制与函数的返回值的数量或可以传递给函数的参数的数量有关,因此不能超过参考....请注意,这可能不是一般情况,写入{ unpack(t) } 可能导致不复制所有数组部分t.

编写函数的效率稍低一点就是在传递的参数上写一个循环,这是我原来答案中的版本.这看起来如下:

function equation:init(...)
    self.equation = select(1, ...)
    self.pipe = {(select(1,...))}
    self.selected = 1

    -- Loop arguments to add answers.
    local t = {}
    for i = 2, select("#",...) do
        t[#t+1] = select(i,...)
    end
    self.answers = t
end
Run Code Online (Sandbox Code Playgroud)

  • 我花了最后一个半小时试图弄清楚为什么直接从书中复制的示例不起作用,并且“arg”总是“nil”或垃圾数据。非常感谢解释 `...` 语法从根本上改变了 Lua 5.0 和 5.1 之间的行为! (5认同)
  • 哇,非常感谢您的详细回答!这确实正是我的意思。我期望“...”创建一个名为“arg”的表,但这没有发生。再次感谢你的帮助! (2认同)
  • 更正 - select(n, ...) 不返回第 n 个参数:相反,它返回第 n 个参数以及所有后续参数。 (2认同)
  • @AmrBekhit,对,一个容易被忽视的细节.`select(n,...)`返回第n个和后面的参数,它通常被上下文缩小到nth.但是,这个属性在这里很有用,所以我会更新我的答案. (2认同)

lhf*_*lhf 24

尝试

function equation:init(...)
     local arg={...}
Run Code Online (Sandbox Code Playgroud)

  • 这解决了这个问题.但为什么它不像互联网上提倡的那样有效? (5认同)