rluaでRustのプログラム内でLuaが動いても使いこなせないのはちょっとしょんぼりだな。
ということでLua自体の理解を深めようということになりました。
とはいえまるっきり知らないわけでもなく半端に知識があるところからの補間になるので誰かの役に立つかすら怪しい。自分用のメモなんだなとか思ってもらえればよいかと思う。
複数行のコメント
--[[
コメント
--]]
--[[ コメント ]]
!= , && , ||, null
Luaで!=
は~=
になる。これは初めて見た。
強烈なので一発で覚えられたけど。
&&、||は andとor。Pythonと一緒。
nullはnil
文字列をつなぐ
a .. b
string.format("%s%s", a, b)
など
改行なしの文字表示
io.write("bra")
forの書式
for i = start, end, <step> do
print(i)
end
とか
for k, v in pairs(tbl) do
print(k .. " : " .. v)
end
とかする。
do~end ブロック
とくにforとか専用というわけではなくそれ単体でも使える。
処理のかたまりの目安とかにもできる
++、 += など
Luaにそんなものはないのでa = a + 1
と、まじめに書く。
OOP風
Member = {}
Member.new = function(name, age)
local obj = {}
obj.name = name
obj.age = age
obj.show = function(self)
print(string.format("name: %s (%d)", self.name, self.age))
end
return obj
end
m = Member.new("Taro", 32)
m:show()
ポイントは最後のm:show()
のコロン。自分自身のテーブルを引数として渡す動作をするので
関数のselfにmが入ることになる。
通常通りピリオドで処理した場合、自分自身の参照が必要なのでm.show(m)
と記述する必要があり少々冗長
テーブルについて
テーブルは配列的にも使えるし連想配列的にも使える。
配列的に使う、この場合暗黙的にインデックス値がキーとして与えられており、シーケンシャルなデータとなる。結構有名な話としてLuaのシーケンスは1から始まる。
tbl = { 1, 2, 3 }
連想配列的に使う。Rustと同じく要素の順序は保証されない。
tbl = {"name" = "Hanako", age = 23 }
内容をとりだす
どちらの場合でもイテレーション処理で内容を取り出すことが出来る
for key, value in pairs(tbl) do
print(key .. " : " .. value
end
要素数を取得する
テーブルの要素は、シーケンシャルの場合は
#tbl
などとして取り出すことが出来るが連想配列的に利用している場合この方法では要素がどれだけあっても要素数0という答えになる。
イテレーション処理でカウントを取るなどして要素数を得る必要がある(ほんと?)
値の追加、削除
table.insert(tbl, {name="Alice", age=19})
table.remove(tbl)
table.insertとtable.removeを利用。
table.removeは最後のデータから削除される。
ソート
table.sort(tbl)
キー一覧を取得したい
そのような機能はないのでイテレーション処理で別のテーブルにキーを書き出すなどする。
あと、そのような処理が必要にならないように処理を見直した方がいいかもしれない。
メタテーブルという仕組みがある
テーブルの実データに影響を与えないメタデータを記録したりできる機能
フラグの管理やデータの型の管理などに便利かもしれない?
必要そうになったらそういうものがあると思い出して調べる
Luaでは関数も値
値なので変数に入る、テーブルにだって入る。
a = function(n); print(n); end
a(123)
b = {a, ....}
グローバル変数
_VERSION
を取得すると現在動作中のLuaのバージョンが取得できる。
それ以外のグローバル変数は_G
または_ENV
にすべて入っている。
ということはPythonでは出来たhelp("modules")
みたいなのが出来る。
help = function(name)
local e
if name == "" or name == nil then
e = _ENV
else
e = _ENV[name]
end
if name ~= nil then
print(string.format("\n\n\"%s\" is %s", name, type(e)))
end
print("--------------------")
if type(e) == "table" then
for i in pairs(e) do
print(i .. " ... " .. type(e[i]))
end
end
print()
end
# help()
--------------------
rawset ... function
math ... table
dofile ... function
tostring ... function
((中略))
_VERSION ... string
loadfile ... function
引数を指定しなければ全体を表示してくれる。
タイプとしてはfunction以外にtableやstring、numberなどがある。
tableについては次のように指定すれば中を調べられる。
help("math")
"math" is table
--------------------
min ... function
sqrt ... function
ldexp ... function
asin ... function
((中略))
rad ... function
exp ... function
どういう関数が現在の環境で使えるのか調べることが出来る。
なんだ、Luaもできるんじゃん。
で、いちいちコード書き換えるのが面倒なのでREPLを作った。
local s
while true do
io.write("# ")
s = io.read("*l")
assert(load(s))()
end
先ほどのhelp functionと一緒に書いてやればコードを試したりしつつhelpで機能の確認などをすることが出来る。
わーお、便利だね。
でも簡易実装のREPLだからエラーがあると容赦なくストップする。
とりあえずこんなところかと思う。
他にも面白そうな話があれば追記したりするかもしれない。