metatableと文字列連結
尊敬する @shunuhsせんせーが梅.py hackathonにて「華麗なるlua講座」を執り行うとの事。残念ながら僕は用事にて出席できなく、非常に残念なのと申し訳ないのとで、せめても、となんかエントリ書いてみる。
luaの特徴というとやはり、C/C++に簡単に組み込める事と、そのI/Fがスタックベースというバイナリアンには非常に分かりやすい考え方なのと、低フットプリントであること、そのくせmetatableの概念により簡単にクラスもどきが作れて、しかも演算子のオーバーライドも可能、というウマいヤスいハヤい(?)だったりする。しかし気に入らない部分もいくつか
- 配列(実はその実態はtable、このあたりもJSっぽい)が1はじまり
- 文字列連結が .. ってなに、分かりにくい
てなところ(ワガママ・・・)。この2番目をなんとかしてみようとか。
metatable
luaではtableに metatableを指定して、各種挙動をコントロールする事ができる。例えば __tostring(文字列に変換するメソッド), __index(キーが無い場合に呼ばれるメソッド・・・要するにこれをインスタンスメソッドに使う)とか__add, __subとかの演算系メソッドなどがある。設定は単純にこれらの名前で作ったtableを
t = {} setmetatable(t, { __tostring = function() .... end } )
のようにひも付けしてやればオK。上の例だと文字列にしようとすると上記のラムダが呼び出される。
文字列連結
というわけでこれを使って _addをひも付けしてやれば + で連結できるという仕組み。
> a = {val="tugi"} > b = {val="hagi"} > S = {__add = function(s1, s2) return s1.val .. s2.val end} > setmetatable(a, S) > setmetatable(b, S) > print(a+b) tugihagi
結局クラスにしてしまうのが正解かな。
String = {} function String:new(str) t = {} t.string = str String.__index = String String.__add = function (left, right) return String:new(left.string .. right.string) end String.__tostring = function (str) return str.string end setmetatable(t, String) return t end a = String:new("tugi") b = String:new("hagi") print (a); print (b); print (a+b);
でけた。
sardine% lua String.lua tugi hagi tugihagi
おkっぽい。