web-dev-qa-db-ja.com

可変数の関数引数Lua5.1

私のLuaスクリプトでは、可変数の引数を持つ関数を作成しようとしています。私の知る限り、以下のように動作するはずですが、どういうわけか、TI-NSpireのLua 5.1でエラーが発生します(グローバル引数はnilです)。私は何が間違っているのですか?ありがとう!

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

ルイスの答え 言語の初心者よりも簡潔な人が望むなら、正しいです。うまくいけば、さらに混乱を招くことなく、少し詳しく説明しようと思います。

あなたの質問は、TI計算機の特定のモデルに埋め込まれたLuaのコンテキストにあります。そのため、スタンドアロンのLuaとは異なる詳細がありますが、ほとんどの場合、それらの詳細は、環境で使用できるライブラリと関数に関連しています。 Luaの組み込みバージョンが、作成者によって配布されたスタンドアロンのLuaと大幅に異なることは(Luaはオープンソースであるため可能ですが)珍しいことです。 ( Lua Binaries は、多くのプラットフォーム用のバイナリのリポジトリです。 Lua for Windows は、Windows用のバッテリーを含む完全なディストリビューションです。)

サンプルコードには、計算機フレームワークによって提供されるクラスシステムとインターフェイスするために必要な詳細の交絡因子があります。その詳細は、ほとんどの場合、equationオブジェクトと呼び出されているequation:init()関数の間に接続がないように見えます。それを接着することができる技術があるので、それはただ気を散らすものです。

私が理解しているあなたの質問は、可変個引数関数(可変数の引数を持つ関数)がLuaでどのように宣言され実装されているかについての混乱に要約されます。 Luisの回答に対するコメントから、Luaでのプログラミングのオンライン版(別名PiL)を読んでいます。あなたは セクション5.2 を引用しました。 PiLは、言語の背景についての優れた情報源です。残念ながら、可変個引数関数は流動的な機能の1つです。オンラインの本のエディションはLuaバージョン5.0の時点で正しいですが、TI計算機はおそらくLua5.1.4を実行しています。

Lua 5では、可変個引数関数は、残りの引数を表す記号_..._で終わるパラメーターリストで宣言されています。 Lua 5.0では、呼び出しは、_..._に一致する引数を含むテーブルを含むargという名前の「魔法の」ローカル変数を使用して実装されていました。これには、すべての可変個引数関数が呼び出されたときにテーブルを作成する必要がありました。これは、ガベージコレクターに不要なオーバーヘッドとプレッシャーをかける原因になります。そのため、Lua 5.1では、実装が変更されました。_..._は、呼び出された関数で一致する引数のエイリアスとして直接使用できますが、実際にはテーブルは作成されません。代わりに、引数の数が必要な場合はselect("#",...)と記述し、n番目の引数の値が必要な場合はselect(n,...)と記述します。

あなたの例の交絡因子は、クラスシステムに戻ってきます。関数equation:init(...)を宣言します。この宣言はコロン構文を使用しているため、equation.init(self,...)を記述するのと同じです。したがって、最終的にクラスフレームワークが___call_メタメソッドを使用して呼び出されると、実際の最初の引数はselfという名前になり、0個以上の実際の引数は_..._と一致します。

以下の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
_

上記の改訂版では、最初の引数である要素を1つだけ含むテーブルを作成するために{(select(1,...))}を記述し、残りのすべての引数を含むテーブルを作成するために{select(2,...)}を記述しました。この方法でテーブルに挿入できる値の数には制限がありますが、その制限は関数の戻り値の数または関数に渡すことができるパラメーターの数に関連しているため、 _..._への参照が超過しました。これは一般的には当てはまらない可能性があり、{ unpack(t) }canと書くと、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
_
37
RBerteig

試してみてください

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