Luaで演算子オーバーロード
2009 年 4 月 17 日
Luaには、メタテーブルと言う機構があり、テーブルに割り当てることで、演算子オーバーロードが実現できます。
メタテーブルをあらかじめ作成し、指定したテーブルに割り当てを行うことで動作します。
そこで、試しに配列のマージを+演算子でできるようにしてみます。
Array_meta = {
__add = function(x,y)
z = {}
for i=1,#x do
table.insert(z, x[i])
end
for i=1,#y do
table.insert(z, y[i])
end
return z
end
}
function Array(...)
local tbl = {...}
setmetatable(tbl, Array_meta)
return tbl
end
t1 = Array(1,2,3,4,5,6,7,8,9,10)
t2 = Array(2,4,6,8,10)
t3 = t1+t2
for i=1,#t3 do
print(string.format("#%02d %d", i, t3[i]))
end
1行目から12行目までが、Array_metaと言う名前でメタテーブルを定義しています。
__add関数が加算演算子(+)の演算子オーバーロード部分です。
この間数内で配列をつなぎ合わせています。
13行目から17行目までが、Array関数の定義です。
PHPのarray関数のように、引数で配列の初期化を行い、テーブルを生成して返します。
15行目が作ったテーブルに対して、Array_metaをメタテーブルとして関連付けしています。
これにより、テーブルへの+演算子がオーバーロードされます。
22行目でテーブルt1とテーブルt2を+記号でつなげています。t3は__add関数が呼ばれた結果が入ります。
メタテーブルには、__add以外にも多くの演算子の定義が可能です。
| 演算子 | メタテーブル関数名 |
|---|---|
| + | __add |
| - | __sub |
| * | __mul |
| / | __div |
| % | __mod |
| ^ | __pow |
| ..(結合演算子) | __concat |
| - (変数前のマイナス記号として) | __unm |
| #(変数前の要素数取得記号として) | __len |
| == | __eq |
| < | __lt |
| <= | __le |
色々作ってみましょう。
ただし、多用すると記述内容と実際の動作が予想できなくなるなど副作用もあるため、
最低限にしておきましょう。
今回の例でも、配列を行列とみなす場合は、__addよりも__concatを使った方がより分かりやすいのです。
ただし、配列同士を..でつないだ場合は、文字列に変換してつなげる方が嬉しい人もいるでしょう。
この辺の判断が難しいのです・・・