微妙にわかりにくいので整理いたします。
lua-5.2 から unpack は消えて table.unpack になりました。
http://www.lua.org/manual/5.2/manual.html#8
Function unpack was moved into the table library and therefore must be called as table.unpack.
impl | lua version |
---|---|
nvim | 5.1(luajit) |
wezterm | 5.4 |
nyagos | 5.1(gopher lua) |
MoonSharp | 5.2 |
unpack は table から関数の多値 return への変換である
multiple result
unpack はそもそも何をしているのかというと、table を多値 return している。
lua の関数引数と戻り値は stack 経由
lua からは、関数呼び出しの stack は見えないのだけど C の方はこうなっている。
function f(1, 2, 3)
--- stack3 3
--- stack2 2
--- stack1 1 👈 引数が stack につまれた状態で関数に入る
--- 関数本体
return 4, 5, 6
--- stack6 6
--- stack5 5
--- stack4 4 👈 戻り値を stack に上乗せして関数から戻る
--- stack3 3
--- stack2 2
--- stack1 1
end
unpack の動作イメージ 👇
function unpack(t)
--- stack1 t = {1, 2, 3} 👈 引数が stack につまれた状態で関数に入る
--- 関数本体
return t[1], t[2], t[3]
--- stack4 t[1] = 3
--- stack3 t[2] = 2
--- stack2 t[3] = 1 👈 戻り値を stack に上乗せして関数から戻る
--- stack1 t = {1, 2, 3}
end
複数戻り値は複数代入で受けれるので、unpack と 複数代入を組み合わせることで、
table を分解するように動く。
local t = {1, 2, 3}
local n1, n2, n3 = table.unpack(t)
プログラミング用語的には、多値、多値返却というらしい?。
table を直接分解することはできない。
local t = {1, 2, 3}
-- lua ではこれはできない
local n1, n2, n3 = t
他の言語の見た目が似たような機能、
C#のDeconstruct
、
c++の構造化束縛
、
pythonのtuple分解
とちょっと違う機能なのです。
...
との関連
vararg expression
可変長引数。
Vararg expressions, denoted by three dots ('...'), can only be used when directly inside a vararg function
function f(...) -- 👈 これ
end
別の関数にそのまま渡す
function f(...)
print(...)
end
table 化する
function f(...)
local t = {...}
print(t)
end
> f(1, 2, 3)
table: 0xa00050f90
return する
めったに使わないと思うが OK。
function f(...)
return ...
end
> print(t(1, 2, 3))
1 2 3
注意
function f(...)
local x=... -- 👈 先頭の一個だけ代入する意味になる
return x
end
function f(...)
print('x', ..., 'y') -- 👈 先頭の一個だけ使われる
end