Lua で気を付けること
lua初学者のため記事中で間違ってることがあるかもしれません。
目次
変数
https://www.lua.org/manual/5.4/manual.html#3.3.3
local
付けておけば間違いない
local s = "hello world"
多重代入できる
local a, b, c = 10, 20, 30
数値
+=
とか -=
、n++
とか --n
は無いので愚直に n = n + 1
をやる。
/
は小数点以下まで //
は端数切り捨て。
print(10 / 3) -- 3.3333333333333 print(10 // 3) -- 3
Neovim では :lua print(10 // 3)
とか :call luaeval('print(10 // 3)')
をやると E5107: Error loading lua [string ":lua"]:1: unexpected symbol near '/'
というエラーになる
文字列
文字列の連結は ..
local a = 'hello' local b = a .. " " .. "world" print(b) -- hello world
文字列に関する関数
https://www.lua.org/manual/5.4/manual.html#6.4
関数は string.len
と s:len
のどっちでも書ける
local s = 'hello' print(string.len(s)) -- 5 print(s:len()) -- 5
配列/ハッシュテーブル
https://www.lua.org/manual/5.4/manual.html#3.4.9
配列もハッシュテーブルも lua では table
local t1 = { 10, 20, 30 } local t2 = { ["foo"] = 10,["bar"] = 20,["baz"] = 30 } print(t1[1]) -- 10 print(t2.foo) -- 10
テーブルのインデックスは 1 から始まる。 [0]
は nil
でエラーにはならない。
local t = {10, 20, 30} print(t[0]) -- nil print(t[1]) -- 10 print(t[2]) -- 20 print(t[3]) -- 30 for i, v in pairs(t) do print(i, v) -- 1 10 -- 2 20 -- 3 30 end
テーブルには配列とハッシュテーブルが併存する。
local t = { 10,["key"] = "value", true } print(t[1]) -- 10 print(t[2]) -- true print(t['key']) -- value print(t[3]) -- nil for k, v in pairs(t) do print(k, v) -- 1 10 -- 2 true -- key value end
ipairs
とかいうやつ。pairs
との違いは 1 からの連番で途切れたところで終了するっぽい。それと本物の [2]
は最後の 40
local t = { 10,[2] = 20,[100] = 100,[3] = 30, 40 } for i, v in ipairs(t) do print(i, v) -- 1 10 -- 2 40 -- 3 30 end
テーブルの長さ(length)は table.len(t)
ではなく #t
local t = { 10, 20, 30 } -- print(t:len()) -- attempt to call a nil value (method 'len') local t = { 10, 20, 30 } for i = 1, #t do print(t[i]) -- 10 -- 20 -- 30 end
テーブルに関する関数
https://www.lua.org/manual/5.4/manual.html#6.6
論理演算子
https://www.lua.org/manual/5.4/manual.html#3.4.5
&&
は and
で ||
は or
で !
は not
if true and true then print("is true") -- is true end if true or false then print("is true") -- is true end local ok = false if not ok then print("not ok") -- not ok end
三項演算子
local n = true and 100 or 200 print(n) -- 100
比較演算子
https://www.lua.org/manual/5.4/manual.html#3.4.4
not equal の !=
は Lua では ~=
空文字とかゼロは true
で、多分 nil
と false
が偽
local s, n = '', 0 print(s and n and "is true" or "is false") -- is true print(nil and "is true" or "is false") -- is false print(false and "is true" or "is false") -- is false
正規表現/パターン
https://www.lua.org/manual/5.4/manual.html#6.4.1
エスケープ文字は \
ではなく %
local pattern = '^h[%w]+%s[%u%l]+d$' print(("hello world"):match(pattern) ~= nil)
\t
とか \n
の制御文字は %c
を使うか16進数で \x09
とか十進数で \9
とかするっぽい。
print(("\t"):match('\x09') ~= nil) -- true print(("\n"):match('\x0A') ~= nil) -- true print(("\r"):match('\x0D') ~= nil) -- true print(("a"):match('\x61') ~= nil) -- true print(("\t"):match('\009') ~= nil) -- true print(("\n"):match('\010') ~= nil) -- true print(("\r"):match('\013') ~= nil) -- true print(("a"):match('\097') ~= nil) -- true
switch/case/select 文
switch
/ case
/ select
は構文として無いので if
で頑張る。
ループ while/for/repeat
break
はあるけど continue
は無い。予約語(Lexical Conventions)参照
https://www.lua.org/manual/5.4/manual.html#3.1
local i = 0 while i < 10 do if i == 5 then break end -- continue の代わりに i ~= 3 で 3 をスキップ if i ~= 3 then print(i) end i = i + 1 end
for
文は for i = 0; i < l; i++ do
ではない。ruby の times
みたいなもん
for i = 0, 5 do print(i) -- 0 -- 1 -- 2 -- 3 -- 4 -- 5 end
repeat
は do ... while
じゃない。その名の通り ..まで
ruby にも until
あるけどややこしいから使わないやつ
local i = 0 repeat print(i) i = i + 1 until i > 5
関数
可変長引数。...
は { ... }
でテーブル化するっぽい
local function fn(...) local t = { ... } for i, v in pairs(t) do print(i, v) -- 1 foo -- 2 bar -- 3 baz end end fn('foo', 'bar', 'baz')
型が string
だからと split
するとエラー。 ...
こいつの正体はわからん
local function fn(...) print(type(...)) -- string local s = ... local t = s:split(' ') end
即時関数
(function(a, b, c) print(a, b, c) end)('foo', 'bar', 'baz')
クラス
基本的なクラスの書き方。xxx.xxx
がスタティックメソッドだろうけどインスタンスからも呼び出せる。その場合以下の p.print(p)
みたいなダサいことになる
local Profile = {} function Profile:new(name, age) local t = setmetatable({}, { __index = Profile }) t.name = name t.age = age return t end function Profile:print() print(self.name, self.age) end function Profile.print(self) print(self.name, self.age) end local p = Profile:new('Ohtani', 28) p:print() -- Ohtani 28 p.print(p) -- Ohtani 28 Profile.print(p) -- Ohtani 28 p.name = 'Yoshida' p.age = 29 p:print() -- Yoshida 29
メタテーブルの __add
を使って文字列の連結演算子を +
風にしてみたり
https://www.lua.org/manual/5.4/manual.html#2.4
local String = { ['mt'] = {} } function String.new(value) local t = setmetatable({}, String.mt) t.value = value return t end function String.mt:__tostring() return self.value end function String.mt.__add(a, b) return String.new(a.value .. " " .. b.value) end local a = String.new("foo") + String.new("bar") + String.new("baz") print(tostring(a)) -- foo bar baz