TI-Nspire & Lua / スクリプティングのヒント / メタテーブルを使う 2 / 新しくリスト型のデータを作って要素同士の四則演算ができるようにする

-- リスト同士のサイズの相違は想定しない。
-- 穴あきリストは想定しない。
-- 数値以外は想定しない。


-- リスト同士の四則演算を行うためのメタメソッドを定義する。
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)

f:id:ti-nspire:20170210075705p:plain

参考: 入門Luaプログラミング, p.158-160