golangの日記

Go言語を中心にプログラミングについてのブログ

Lua で気を付けること

lua.png


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.lens: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 で、多分 nilfalse が偽

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


repeatdo ... 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