ちょっと某FtD周りで知りたくなったのでチートシート代わりにまとめを作っておく。
公式はここ https://www.lua.org/home.html
基本
- スクリプト言語。Lua VMで動作する。
- C/C++で書かれたホストプログラムへ組み込まれることが目的だったらしい。
- 実際「本体はともかくスクリプトはLua」というのは割とよく見る。どれがと言われるとかえって困るぐらいよく見る。
- 移植性が高い。
- やたら速い。
- JITコンパイラを使うとJavaに近い速度が出るとか(ホントかよ!)
- 動的型付け、プロトタイプ型オブジェクト指向。
- MITライセンス。
- ガベージコレクションあり。
- コルーチンあり。
型
使用する際、必要に応じて相互変換が行われる。
非値 (nil)
- いつもの。
- 宣言直後はこれ。
boolean
- いつもの。
number
- double相当らしい。
- intはない。あらゆる数値はnumber=doubleである。
string
- 結合は .. 演算子。
- Cと同様の構造。ヌル文字はnilが代行している。
function
- JavaScriptあたりと同様ポンポンできる。
table
- 連想配列。nilでなければキーにも値にもできる。
- キーを整数にすると内部で配列扱いされて高速化する。
- 配列のインデックスは1オリジンにするのがお約束。めずらしー
- {} で作れる。
foo = {}
と言った具合。 - インデックス・アクセスは [] 。いつもの。
他、C連携向けのuserdataやコルーチン用のthreadが存在。
文法周り
コメント
ハイフン2連打で一行コメント。その後ろに角カッコ2連打で多行コメント。
-- 一行
--[[
多行
コメント
]]
多行コメントは --[[ でないと認識されないため、コメントアウトするときはこうすると切り離しが楽……らしい。シンタックスハイライトがないと事故りそうだ
-- これを
--[[
hogehoge
--]]
-- こうする
---[[
hogehoge
--]]
変数
宣言無し、代入で生成するタイプ。
グローバルが基本であり、ローカル変数がほしいときは頭にlocalを付けて local var = 1
とでもする必要がある。
また多重代入が可能なのも特徴。 foo, bar = 1, 2
なんてのも可能な上、これを利用してスワップまでできる。
演算子
なお、各演算子に対応する処理は全てメタメソッドという形で定義されている。
各オブジェクトのメタメソッドをいじることで演算子オーバーライドが可能。
算術
お約束の加減乗除と剰余 +-*/% に加え累乗 ^ や切り捨て除算 // が用意されている。当然単項マイナス - もある。
+= や ++ は存在しない。
比較
==、<、<=、>、>=まではいつもの。not equalだけ~=と少々独特。
==、~=に限っては型変換は行われず、型が違えばその時点で判定が下る。要するに 0~="0"
はtrueである。
連結
先述の通り..で文字列を結合する。
ビット演算
AND & 、OR | 、XOR ~ 、左右ビットシフト << >> 、単項NOT ~ が用意されている。
長さ演算子
単項演算子 # 。
文字列の長さはバイト単位であるため注意が必要。
またテーブルの長さはCの文字列表現よろしく「最初からnilまで」であるため、nilが途中に存在する場合そこで引っかかる。
制御文周り
お約束のif, for, whileが勢揃い。breakでループを抜けられるところまでお約束どおり。
if COND then
-- true
else
-- false
end
for i=1, 10 do
-- action
end
for i in ary do
-- action
end
while COND do
-- action
end
関数
function hoge(hoge)
-- action
end
f = function() ... end
local function f() ... end -- local f; f = function() ... end 相当
引数はもちろんローカル変数である。
また珍しいことに、Luaは複数の返り値をまとめて返すことができる。
function triple(s)
return s, s, s
end
a, b, c = triple(10)
この「多値」は引数として渡すことができる。
また引数を配列として扱いたい場合、仮引数に ... を置いておけばよい。
逆に配列を実引数のリストとして扱うことも可能 (table.unpack) 。
更に、JSよろしく無名関数を返してクロージャをやったり、coroutineでコルーチンを組んだりできる。なんでもあるのか?
ブロック
制御構文や関数のボディに加え、特有のチャンクというものが存在する。
チャンク
チャンクは文の連続であり、改行によって切り離される。
(セミコロンを連打すると怒られるのはこの都合上空行を内包できないという事情もある)
チャンクは内部的に無名関数である。このためチャンクはローカル変数を持つことも可能。
明示的なブロック
do - endで明示的にブロックを構成することもできる。
また return や break はブロックの末尾以外に入れられない特性を持つため、これのために利用することもあるとか。
エラー処理
例外機構はない。エラー処理はpcall関数で行う。
pcallはProtected Callの意であるらしい。第一引数に呼び出し対象関数、それ以降にその引数を受け取る。
呼び出し対象関数の処理が完了するとその戻り値に加えてbooleanを一つ返す。trueであればエラーはなかったということになるが、falseの場合は一緒にエラーメッセージが返ってくる。エラーメッセージには発生位置の情報が含まれる。
意図的にエラーを発生させたい場合はerror関数を呼べばよい。第一引数でエラーメッセージを指定できる。
また、第二引数でエラーの原因となった呼び出し階層を指定することもできる。1 (デフォルト) で原因行、2で呼び出し元、3で呼び出し元も呼び出し元、といった具合で、0を指定すると表示しなくなる。
疲れたので一旦ここまで。
とりあえず今後困ったら別の記事を追加することにしておく。