2.1 値と型
Lua は動的型付けの言語です。これは変数が型を持たないことを意味します: 型を持つのは値だけです。Lua に型の定義は存在せず、全ての値がそれぞれ型を持ちます。
Lua の値は全てファーストクラスです。つまり全ての値は変数に保存でき、関数の引数として渡すことができ、関数の返り値として使えます。
Lua には八個の基本型があります:
- nil
- 真偽値 (boolean)
- 数値 (number)
- 文字列 (string)
- 関数 (function)
- ユーザーデータ (userdata)
- スレッド (thread)
- テーブル (table)
nil 型の値は nil だけです。値 nil は他のどんな値とも異なることが一番の特徴であり、有効な値が存在しないことを表すのによく使われます。真偽値型の値は false と true の二つです。条件文は nil と false の両方に対して偽となります。この二つの値をまとめて偽値 (false value) と呼び、偽値でない任意の値に対して条件文は真となります。
数値型は整数 (interger) 型と浮動小数点数 (float) 型という二つの部分型を持ち、それぞれ整数と実数 (浮動小数点数) を表します。Lua は標準で 64 ビット整数と倍精度 (64 ビット) 浮動小数点数を使いますが、32 ビット整数と単精度 (32 ビット) 浮動小数点数を使うように Lua をコンパイルすることも可能です。整数と実数を 32 ビットにするオプションは性能の低いマシンや組み込みシステムで特に重要となります (luaconf.h
にある LUA_32BITS
マクロを参照してください)。
特別に設定をしない限り、整数演算におけるオーバーフローはラップアラウンドします。これは 2 の補数を使ったときの自然な演算規則に従う挙動であり、演算の数学的な答えを 2n で割った余りが結果となります (n は整数型のビット幅)。
Lua は算術演算で整数と浮動小数点数のどちらを使うかについて厳密な規則を持ちますが、必要な場合には自動的な変換も行います (§ 3.4.3)。そのためプログラマーは整数と浮動小数点数の違いを基本的に無視するか、全ての数の表現を完全に管理するかを選択できます。
文字列型は変更不能なバイト列を表します。Lua は 8 ビットクリーンです: 文字列の要素は任意の 8 ビット値であり、途中にゼロ ('\0'
) があっても構いません。さらに Lua ではエンコーディングが規定されず、文字列の要素についての仮定は全くありません。ただし文字列の長さは Lua の整数に収まる必要があります。
Lua からは Lua および C で書かれた関数の作成と呼び出しが可能です (§ 3.4.10)。この二つの関数はどちらも関数型で表されます。
ユーザーデータ型は任意の C データを Lua 変数として保存するために提供され、その値は生のメモリ領域を表します。ユーザーデータにはフル (full) とライト (light) の二種類があります。フルユーザーデータは Lua が管理するメモリブロックを表すオブジェクトであり、ライトユーザーデータはただの C ポインタです。Lua はユーザーデータに対する操作として代入と等価判定だけを持ちます。フルユーザーデータの値に対する操作を定義するにはメタテーブルを使います (§ 2.4)。ユーザーデータ型の値の作成と変更は Lua から行うことはできず、C API を通じてのみ可能です。これによりホストプログラムや C ライブラリが持つデータの整合性が保証されます。
スレッド型は独立した実行の流れを表し、コルーチンの実装で利用されます (§ 2.6)。Lua のスレッドはオペレーティングシステムのスレッドとは関係がありません。Lua はスレッドをネイティブにサポートしないシステムを含む全てのシステムでコルーチンをサポートします。
テーブル型は連想配列を実装します。連想配列とは数字以外の値も添え字に使える配列であり、nil と NaN を除いた任意の Lua の値を添え字にできます (NaN は IEEE 754 規格において 0/0 といった不定の計算結果を表すに使われる特殊な浮動小数点数です)。Lua のテーブルは非均一 (heterogeneous) です: つまり、テーブルのバリューは任意の型の値を保持できます。ただし nil は例外で、対応するバリューが nil であるキーはテーブルに存在しないとみなされます。逆に存在しないキーに対応するバリューは nil となります。
テーブルは Lua でデータ構造を作るための唯一のメカニズムです。テーブルを使えば通常の配列・リスト・シンボルテーブル・集合・レコード・グラフ・木といったデータ構造が表現できます。レコードを表現するときはフィールドの名前をテーブルの添え字として使います。レコードを自然に書けるように、Lua はa.name
という記法を a["name"]
の糖衣構文として提供します。Lua にはテーブルを作る便利な方法がいくつか存在します (参照: § 3.4.9)。
テーブルの添え字と同様に、テーブルのフィールドの値も任意の型にできます。特に Lua では関数がファーストクラスの値なので、テーブルのフィールドに関数を保持できます。そのためテーブルを使えばメソッドを実現できます (参照: § 3.4.11)。
添え字を使ってテーブルにアクセスするとき、添え字は Lua における直接的な等価性 (raw equality) の定義に従って比較されます。つまり a[i]
と a[j]
が同じテーブル要素を指すのは i
と j
が直接的に等しい (メタメソッドを使わない比較で等しい) ときであり、かつそのときに限ります。特に整数とちょうど等しい浮動小数点数はその整数と等しいとみなされます (例えば 1.0 == 1
です)。曖昧さを取り除くために、整数と等しい浮動小数点数がテーブルのキーとして使われた場合そのキーは整数に変換されます。例えば a[2.0] = true
と書いたとき実際にテーブル a
に挿入されるキーは整数 2
です。
テーブル・関数・スレッド・(フル) ユーザーデータの値はオブジェクトであり、こういった値を持つ変数に保存されるのは値そのものではなく参照です。こういった値の変数への代入、パラメータの受け渡し、関数からの値の返却は必ず参照を通して行われます。こういった処理はいかなるコピーも意味しません。
ライブラリ関数 type
は与えられた値の型を表す文字列を返します。