1. ホーム
  2. スクリプト・コラム
  3. ルア

Luaの基本的なデータ型、式、フロー制御ステートメント

2022-01-06 11:58:53

1. Luaの型
1.1 基本型

{Lua は動的型付け言語であり、型定義の構文はない。 Luaは動的型付け言語で、型定義のシンタックスはありません。Luaにはnil、boolean、number、string、userdata、function、thread、tableの8つの基本型が存在します。

関数型は、値をもとにその型名(文字列)を返すことができます。例えば、print(type(print)), output "function"; print(type(type(X)), output "string ". ここではXが定義されていてもいなくてもtype(X)は常に文字列を返します)。

1.2 各タイプの注意点

booleanについて。

Luaでは、falseとnilは「偽」、それ以外の値は「真」とみなされます(数字の0や空文字列も含む)。
数字について

この型は実数(倍精度倍数)を表すのに使われ、整数もこの型で表されます。
文字列について。

文字列は、C言語のように文字で直接変更することはできません。必要であれば、文字列ライブラリで新しい文字列を作成する必要があります。文字列は、一致する一重引用符または二重引用符の組によって定義することができます。C言語のようなエスケープシーケンスが実用的である。

さらに、段落全体を含む文字列の場合、改行文字を無視する二重角括弧 [[content]] によって定義することができる。左側の二つの角括弧の間に任意の数の等号を付加した場合、例えば[====[]であれば、右側の文字列は同じ数の等号を付加した角括弧、例えば[====]に一致するはずで、こうすることによって、任意の内容の文字列をエスケープせずに直接埋め込むことができるのです。同様にコメントもこのように使うことができ、例えば --[==[match --]==] のようになります。

Luaは、実行時に数値から文字列への自動変換を行います。例えば print("10" + 1) -> 11, print(10 . .20) -> 1020 ("..." は文字列連結子で、上の例では数字を文字列に変換して連結し、数字と.を連結しています。(と.の間には空白を入れる必要があります)。

自動変換はできるだけ使わず、必要であれば強制的に変換することをお勧めします。関数tonumber(x)はxを数値に変換しようとし,失敗するとnilを返すし,関数tostring(x)はxを文字列に変換する。文字列の前に "#"を置くと、例えばprint(#"length") -> 6のように、文字列の長さを得ることができる。
テーブルについて

テーブルは、nil以外の型の実用的な値のインデックスとして使用できる特殊なインデックスを持つ配列であり、その成長と削除は自動的なメモリ管理によって行われます。テーブルの要素が初期化されていない場合、その値はnilであり、nilを代入することによりテーブルの要素を削除することができる。

p["age"] は p.age と等価である。p.ageとp[age]は等価でないことに注意してください。

"#" は、配列の最後のインデックス値(またはそのサイズ)を返すために使用することができます。例えば、print(a[#a])はリストaの最後の値を表示し、a[#a+1] = io.read() は値を読み込んでリストaの末尾に挿入するものです。配列の途中にnilが含まれている場合、最初のnilが終端とみなされるため、「隙間」のある配列には#を使用しないようにしましょう。

Luaでは、テーブルの最初のインデックスは、C言語では0ですが、デフォルトでは1です。
関数、ユーザデータ、スレッドタイプは後回しにします。
2. 表現方法
2.1. 算術演算子

正規の演算子は以下の通りです。+ 加算、-減算、*乗算、/除算、^指数、%モジュロ。ここで ^ は任意の実数に対して使用でき、たとえば x ^ (-1 / 3) は x の立方根の逆数を計算します。また % は次のように使用できます: x % 1 は x の小数部分を、x - x % 0.01 は x の小数点以下 2 位までの結果を表します。

2.2. 関係演算子

通常の関係演算子は <より小さい、>より大きい、<=以下と等しい、>=以上と等しい、==と等しい、~=と不等である。オブジェクトの場合は、その参照が比較される。

2.3. 論理演算子

論理演算子には、and、or、not があります。and(or) では、最初のオペランドが false (true) の場合は最初のオペランドを返し、そうでない場合は 2 番目のオペランドを返します。例:print(4 and 5) -> 5, print(false or 5) -> 5.

一般的な書き方として、x = x or v という書き方がありますが、これは x が設定されていないときにデフォルトの値 v を設定するために使うことができます。また、max = (x > y) と x or y のように、(a and b) or c という書き方も a ? b : c と同様です。

2.4. 文字列の連結

2つの文字列を連結するには「...」(ドット2つ)を使用し、どちらかが数字であればLuaは自動的に変換します(例:print(0 . 1) -> 01)。文字列の連結は新しい文字列を作成するだけで、元のオペランドを変更することはありません。

Luaの演算子の優先順位は、以下の図の通りです。

2.5. テーブルコンストラクト

上記の{}を直接代入して空の表を作る以外に、day = {"S", "M", "T"} や point = {x = 10, y = 20} などのように値を初期化することも可能である。(i.e. point.x = 10, point.y = 20). 上記の2つの初期化方法を混在させることもできますし、コンマの代わりにセミコロンを使ってリスト部分とレコード部分を明確に分けることもできます。例えば、polyline = {color = "blue"; {x = 0, y = 0}, {x = 10, y = 10}, {x = 20, y = 30}} なら print(polyline[2].x)` -> 10.

より一般的な初期化形式として、opnames = {["+"] = "add", ["-"] = "minus"} のように、角括弧の間にインデックス値を宣言することができます。もし、配列の開始インデックスとしてどうしても0が必要な場合は、days={[0] = "S", "M", "T"}のようにすることができます。ただし、Luaでは0を開始インデックスにすることはお勧めしません。ほとんどの組み込み関数では、配列の開始インデックスは1であると仮定するからです。

3. 順次構造
3.1. 割り当て

Luaでは通常の「=」代入の他に、各変数から各値をカンマで区切って複数代入することができ、常に等号の右側の値の数を左側の変数の数に合わせ、値が少なければ余分な変数にnilを与え、多ければ余分な値は破棄します。例えば、a, b = 10, 2 * x, x, y = y, x のようになります(スワップ)。多重代入は、一般に2つの変数の値を入れ替えたり、関数から複数の戻り値を受け取ったりするために使われます。

3.2. ローカル変数とプログラムブロック

グローバル変数とは対照的に、Luaにはローカル変数も用意されており、変数に修飾子localを付けることで修飾することができます。ローカル変数のスコープは、宣言されたブロック(制御構造の実行体、関数など)に限定される。

インタラクティブモードでは、入力の各行がそれ自体でブロックを形成するため、1つのローカル宣言は何の効果もないことに注意してください。Do-endキーワードの組に内容を記述することで、ブロックを明示的に定義することができる。この方法は、特定のローカル変数のスコープを厳密に制御するために使用することもできます。

慣習として、local foo = fooと書き、ローカル変数fooを作成し、グローバル変数fooの値で初期化する方法がある。後続の他の関数がグローバル変数fooの値を変更した場合、まずここに保存することができる。

4.制御構造
すべての制御構造文は表示された終端を持ちます。if, for, and while は end で終わり、repeat は until で終わります。

4.1. if then else(elseif)ステートメント

フォーマット:if {条件1 その時 elseif {条件2 その時 その他 終了
Luaではswitch文はサポートされていませんので、if elseif文の連続が一般的です。

4.2. while文とrepeat文

書式:while する {ループ 終了

フォーマット:繰り返し {ループ まで
Luaでは、ループ本体内で宣言されたローカル変数のスコープには、ループの条件テストが含まれます。

4.3. 数値的なfor文

書式:for var=exp1, exp2, exp3 do {ループ 終了
上記の式は、var が exp1 から exp2 へ変化し、var を exp3 のステップで増加させることを示しています。ここで exp3 はオプションで、指定しない場合は 1 のステップになります。もし exp2 を math.huge に設定すると、無限ループとなります。

forの3つの式は、ループが始まる前に一度だけ評価され、後で評価されることはない。また、制御変数は自動的にfor文のローカル変数として宣言され、ループの内部でしか見ることができない。

4.4. 一般的なfor文

一般的なforループは、すべての値をイテレータで反復する。例えば、for i,v in ipairs(tableA) do print(v) end, ここでiはインデックス値、vは対応する要素値である。ipairs(array)関数は配列を繰り返し処理し、添え字と要素の値の組を返すのに使われ、pairs(table)関数はテーブルを繰り返し処理し、キーと値の組を返すのに使われ、string.gmatch(string)は文字列にある単語を繰り返し処理するのに使われています。

generic forの応用として、新しいテーブルのキーを元のテーブルのキーと逆にした逆テーブルを作成することができる。

4.5. break文とreturn文

これらの文はどちらも現在の文のブロックから飛び出すために使われ、breakはループの階層を終了させ、returnは関数の実行を終了させます。関数を定義した後で、デバッグのためにその関数の先頭から直接ジャンプしたい場合は、returnステートメントを含む表示doブロックを使用します。