可変長引数の値を一つずつ操作する
はじめに
この記事は、Lua Advent Calendar 2022に投稿したものとなります。
前日までの記事は、リンクを参照してください。
Luaの可変長引数
Luaの関数は可変長引数を扱うことが出来ます。
使い方は、関数の仮引数リストの最後に...
を設定しておくだけです。
また、関数内からもそのまま...
で参照します。
local function func(...)
print(...)
end
func("hoge", "fuga", "foo", "bar")
-- -> hoge fuga foo bar
select()
で一つずつ扱う
可変長引数を一つずつ操作したい場合があると思います。
そんなときはLuaの組み込み関数であるselect
関数を利用します。
この関数は、第一引数にindex
、第二引数に可変長引数を取り、可変長引数のindex
以降の引数を全て返します。(Luaは1-indexです)
local function func(...)
print(select(2, ...))
end
func("hoge", "fuga", "foo", "bar")
-- -> fuga foo bar
しかし、これでは可変長引数を一つづつ処理することは出来ません、そこでselect
関数のindex
に数値以外で唯一指定できる "#"
という文字を利用します。
"#"
を第一引数にすると、第二引数である可変長引数の値の総数を返します。
local function func(...)
print(select("#", ...))
end
func("hoge", "fuga", "foo", "bar")
-- -> 4
また、select
関数の呼び出しを()
で囲むことによって、返される全ての引数における最初の引数のみを返すようにすることができます。
local function func(...)
print((select(1, ...)))
end
func("hoge", "fuga", "foo", "bar")
-- -> hoge
これらのLuaとselect
関数の仕様を利用することで可変長引数を一つづつ処理することができます。
以下がサンプルになります。
local function func(...)
for i = 1, select("#", ...) do
local arg = (select(i, ...))
print(i .. ":" .. arg)
end
end
func("hoge", "fuga", "foo", "bar")
-- -> 1:hoge
-- -> 2:fuga
-- -> 3:foo
-- -> 4:bar
まず可変長引数を取る関数内で、"#"
を利用したselect
関数の実行によって可変長引数の総数分のループを作成します。
そして、そのループの中で、現在のインデックス(サンプル内だと変数i
)を利用するselect
関数の呼び出しを括弧で囲むことによって、インデックス以降の可変長引数の内、最初の一つだけが変数arg
に指定されます。
このような処理を書くことでリストを一つずつ操作するような感じで可変長引数も一つずつ操作することが出来ます。
{...}
を利用してリストに変換する
また、可変長引数は{...}
という式によってリストに変換することも出来ます。
local function func(...)
for i, v in ipairs({ ... }) do
print(i .. ":" .. v)
end
end
func("hoge", "fuga", "foo", "bar")
-- -> 1:hoge
-- -> 2:fuga
-- -> 3:foo
-- -> 4:bar
おわりに
Luaの可変長引数はselect
で一つずつ操作したり、{...}
でリストに変換したりすることができます。
また、Luaに限った話ではありませんが、可変長引数は関数の仮引数リストの最後に設定する必要があります。
筆者はselect
についての説明を書いている途中で{...}
という式を知りました。リファレンスをしっかり読むことは大事だと思います。
Discussion