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})
解决方法
您的问题是在嵌入TI计算器的具体模型中的Lua的上下文中。因此,将会有独立的Lua的细节,但是这些细节主要涉及到您的环境中提供的库和功能。这是不寻常的(尽管Lua是开源的,可能的)嵌入式版本的Lua与其作者分发的独立Lua有很大的不同。 (Lua Binaries是许多平台的二进制存储库,Lua for Windows是一个包含电池的完整的Windows发行版)。
您的示例代码具有与计算器框架提供的类系统接口所需的详细信息的混淆因素。这个细节主要表现为你的方程式和方程式之间没有连接:init()函数被调用。由于有技术可以胶合,这只是一个分心。
你的问题据我所知,这归结为一个混淆,说明在Lua中声明和实现的变体函数(具有可变数量的参数的函数)。从您对Luis答案的评论,您一直在阅读Lua(aka PiL)的在线版本。你引用了section 5.2. PiL是语言背景的一个很好的来源。不幸的是,可变函数是一直存在的特征之一。这本书的版本在线版本是正确的Lua版本5.0,但TI计算器可能运行Lua 5.1.4。
在Lua 5中,一个可变参数被声明为一个参数列表,结尾为符号,代表其余参数。在Lua 5.0中,该调用使用名为arg的“魔术”局部变量实现,该变量包含一个包含与….匹配的参数的表。这需要每个可变函数在调用时创建一个表,这是不必要的开销的来源,对垃圾收集器的压力。所以在Lua 5.1中,实现被改变了:…可以直接在被调用的函数中作为匹配参数的别名,但实际上没有创建表。相反,如果需要参数计数,则写入select(“#”,…),并且如果需要第n个参数的值,则写入select(n,…)。
你的例子中的混乱因素回到了课堂系统。你想声明函数方程:init(…)。因为这个声明使用冒号语法,它等同于写方程式(self,…)。所以,当最终通过类框架调用__call元方法时,真正的第一个参数被命名为self,零个或多个实际的参数将匹配….
正如Amr在下面的评论中所指出的那样,select(n,…)实际上返回了第n个参数中的所有值,这在这种情况下特别有用,用于构建self.answers,但也导致了self.pipe的初始化。
这是我在定义方程式init()时尝试实现的修改的近似值,但请注意,我没有一个TI计算器在手,这是未经测试的:
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的所有数组部分。
编写函数的效率稍差一点就是在传递的参数中写一个循环,这是我原来答案中的版本。这将如下所示:
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