-- リスト同士のサイズの相違は想定しない。 -- 穴あきリストは想定しない。 -- 数値以外は想定しない。 -- リスト同士の四則演算を行うためのメタメソッドを定義する。 function calc(operator) return function(listA, listB) local result = {} for i = 1, #listA do if operator == "+" then result[i] = listA[i] + listB[i] elseif operator == "-" then result[i] = listA[i] - listB[i] elseif operator == "*" then result[i] = listA[i] * listB[i] elseif operator == "/" then result[i] = listA[i] / listB[i] end end return List(result) -- 計算結果を List 型にして返す。 end end -- 数値の符号を反転するためのメタメソッドを定義する。 function signInversion(list) local result = {} for i = 1, #list do result[i] = -list[i] end return List(result) end -- リストを文字列としてコンソールに出力するためのメタメソッドを定義する。{1, 2, 3, ......, n} という形で出力できるようにする。 function listConcat(list) return "{"..table.concat(list, ", ").."}" end -- 上の 3 つのメタメソッドでメタテーブルを定義する。 local listMetatable = { __add = calc("+") , __sub = calc("-") , __mul = calc("*") , __div = calc("/") , __unm = signInversion , __tostring = listConcat } -- 新しく List 型のデータを作るためのコンストラクタを定義する。 function List(list) return setmetatable(list, listMetatable) -- 引数 list にメタテーブル listMetatable をセットする。 end ---------------------------------------------------------------------------------------------------------- -- 確認として、List 型のデータを作って四則演算とコンソール出力とを実行してみる。 -- リストに List() を適用すると、listMetatable というメタテーブルのセットされた List 型データに変換される。 -- List 型データは、listMetatable というメタテーブルがセットされたデータであるため、 -- + 演算子を適用すれば calc("+")() が実行され、print() を適用すれば listConcat() が実行される。 -- - 符号を適用すれば、リストに含まれている数値の符号が反転する。 ---------------------------------------------------------------------------------------------------------- a = List({1, 2, 3, 4, 5}) print(a) print(-a) print(a+a+a) print(-a-a-a) print(a*-a) print(a*-a*-a) print(a/-a/a*-a)
参考: 入門Luaプログラミング, p.158-160