可变数量的函数参数 Lua 5.1 [英] Variable number of function arguments Lua 5.1

查看:18
本文介绍了可变数量的函数参数 Lua 5.1的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的 Lua 脚本中,我试图创建一个带有可变数量参数的函数.据我所知,它应该像下面一样工作,但不知何故,我在 TI-NSpire 上遇到了 Lua 5.1 错误(全局参数为零).我究竟做错了什么?谢谢!

In my Lua script I'm trying to create a function with a variable number of arguments. As far as I know it should work like below, but somehow I get an error with Lua 5.1 on the TI-NSpire (global arg is nil). What am I doing wrong? Thanks!

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})

推荐答案

Luis 的答案 是正确的,如果比初学者​​可能希望的语言简洁.我会试着详细说明一下,希望不会造成额外的混乱.

Luis's answer is right, if terser than a beginner to the language might hope for. I'll try to elaborate on it a bit, hopefully without creating additional confusion.

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

Your question is in the context of Lua embedded in a specific model of TI calculator. So there will be details that differ from standalone Lua, but mostly those details will relate to what libraries and functions are made available in your environment. It is unusual (although since Lua is open source, possible) for embedded versions of Lua to differ significantly from the standalone Lua distributed by its authors. (The Lua Binaries is a repository of binaries for many platforms. Lua for Windows is a batteries-included complete distribution for Windows.)

您的示例代码有一个令人困惑的因素,即它需要与计算器框架提供的类系统交互的细节.该细节主要表现为 equation 对象与被调用的 equation:init() 函数之间没有联系.既然有技术可以把它粘起来,那只是一种干扰.

Your sample code has a confounding factor the detail that it needs to interface with a class system provided by the calculator framework. That detail mostly appears as an absence of connection between your equation object and the equation:init() function being called. Since there are techniques that can glue that up, it is just a distraction.

据我所知,您的问题归结为关于如何在 Lua 中声明和实现可变参数函数(具有可变参数数量的函数)的困惑.根据您对 Luis 回答的评论,您一直在阅读 Lua 编程(又名 PiL)的在线版本.您引用了第 5.2 节.PiL 是该语言背景的良好来源.不幸的是,可变参数函数是不断变化的特征之一.网上书的版本是Lua 5.0版本是正确的,但是TI计算器可能运行的是Lua 5.1.4.

Your question as I understand it boils down to a confusion about how variadic functions (functions with a variable number of arguments) are declared and implemented in Lua. From your comment on Luis's answer, you have been reading the online edition of Programming in Lua (aka PiL). You cited section 5.2. PiL is a good source for background on the language. Unfortunately, variadic functions are one of the features that has been in flux. The edition of the book on line is correct as of Lua version 5.0, but the TI calculator is probably running Lua 5.1.4.

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

In Lua 5, a variadic function is declared with a parameter list that ends with the symbol ... which stands for the rest of the arguments. In Lua 5.0, the call was implemented with a "magic" local variable named arg which contained a table containing the arguments matching the .... This required that every variadic function create a table when called, which is a source of unnecessary overhead and pressure on the garbage collector. So in Lua 5.1, the implementation was changed: the ... can be used directly in the called function as an alias to the matching arguments, but no table is actually created. Instead, if the count of arguments is needed, you write select("#",...), and if the value of the nth argument is desired you write select(n,...).

您示例中的一个混杂因素回到了班级系统.您想声明函数 equation:init(...).由于此声明使用了冒号语法,因此等效于编写 equation.init(self,...).因此,当最终通过类框架使用 __call 元方法调用时,真正的第一个参数被命名为 self 并且零个或多个实际参数将与 匹配....

A confounding factor in your example comes back to the class system. You want to declare the function equation:init(...). Since this declaration uses the colon syntax, it is equivalent to writing equation.init(self,...). So, when called eventually via the class framework's use of the __call metamethod, the real first argument is named self and the zero or more actual arguments will match the ....

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

As noted by Amr's comment below, the expression select(n,...) actually returns all the values from the nth argument on, which is particularly useful in this case for constructing self.answers, but also leads to a possible bug in the initialization of self.pipe.

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

Here is my revised approximation of what you are trying to achieve in your definition of equation:init(), but do note that I don't have one of the TI calculators at hand and this is untested:

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

在上面显示的修订版本中,我编写了 {(select(1,...))} 来创建一个表格,该表格仅包含一个作为第一个参数的元素,并且 {select(2,...)} 创建一个包含所有剩余参数的表.虽然以这种方式可以插入表中的值数量有限制,但该限制与函数的返回值数量或可以传递给函数的参数数量有关,因此不能超过了对 ... 的引用.请注意,通常情况并非如此,编写 { unpack(t) } 可能 导致不复制 t.

In the revised version shown above I have written {(select(1,...))} to create a table containing exactly one element which is the first argument, and {select(2,...)} to create a table containing all the remaining arguments. While there is a limit to the number of values that can be inserted into a table in that way, that limit is related to the number of return values of a function or the number of parameters that can be passed to a function and so cannot be exceeded by the reference to .... Note that this might not be the case in general, and writing { unpack(t) } can result in not copying all of the array part of t.

编写函数的一种效率稍低的方法是对传递的参数编写一个循环,这是我原始答案中的版本.如下所示:

A slightly less efficient way to write the function would be to write a loop over the passed arguments, which is the version in my original answer. That would look like the following:

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

这篇关于可变数量的函数参数 Lua 5.1的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆