3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Luaの理解を深めたかった

Last updated at Posted at 2024-03-02

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だからエラーがあると容赦なくストップする。

とりあえずこんなところかと思う。
他にも面白そうな話があれば追記したりするかもしれない。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?