Подтвердить что ты не робот

Переменная количество аргументов функции Lua 5.1

В моей Lua script Я пытаюсь создать функцию с переменным числом аргументов. Насколько я знаю, он должен работать, как показано ниже, но почему-то я получаю сообщение об ошибке с Lua 5.1 на TI-NSpire (глобальный аргумент равен нулю). Что я делаю не так? Спасибо!

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

Ответ 1

Ответ Луиса прав, если, к сожалению, может быть труднее, чем новичок. Я постараюсь немного разобраться в этом, надеюсь, не создавая дополнительной путаницы.

Ваш вопрос находится в контексте Lua, встроенного в определенную модель калькулятора TI. Таким образом, будут детали, которые отличаются от автономных Lua, но в основном эти детали будут касаться того, какие библиотеки и функции доступны в вашей среде. Это необычно (хотя, поскольку Lua является открытым исходным кодом, возможно) для встроенных версий Lua значительно отличается от автономного Lua, распространяемого его авторами. (Lua Binaries - это хранилище двоичных файлов для многих платформ. Lua для Windows - полный комплект поставки для Windows.)

В вашем примере кода есть сводящий фактор к деталям, которые ему необходимы для взаимодействия с системой классов, предоставляемой каркасом калькулятора. Эта деталь чаще всего выглядит как отсутствие связи между вашим объектом equation и вызываемой функцией equation:init(). Поскольку есть методы, которые могут склеить это, это просто отвлечение.

Ваш вопрос, как я понимаю, сводится к путанице в том, как переменные функции (функции с переменным числом аргументов) объявляются и реализуются в Lua. Из вашего комментария к Luis answer, вы читаете онлайн-версию программы Programming in Lua (aka PiL). Вы указали раздел 5.2. PiL - хороший источник для фона на языке. К сожалению, вариативные функции - одна из функций, которая была в движении. Издание книги на линии верное, как в версии Lua версии 5.0, но калькулятор TI, вероятно, работает с Lua 5.1.4.

В Lua 5 объявлена ​​переменная функция с перечнем параметров, который заканчивается символом ..., который обозначает остальные аргументы. В Lua 5.0 вызов был реализован с помощью "магической" локальной переменной с именем 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

В пересмотренной версии, приведенной выше, я написал {(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

Ответ 2

Try

function equation:init(...)
     local arg={...}