演算子[]
式は値を持つものです。リテラル(数値、文字列、true、false、nil)、無名関数宣言、テーブルコンストラクタ、変数参照、関数呼び出し、可変表現、括弧で囲まれた式、式に適用される単項演算子、および2項演算子と組み合わせた式。
ほとんどの式は1つの値を持ちます。関数呼び出しと可変引数式には、任意の数を指定できます。関数呼び出しまたは可変引数式を括弧で囲むと、最初の値以外はすべて失われます。
式リストは、コンマ区切りの式のリストです。最後の式を除くすべてが1つの値に強制されます(追加の値を削除するか、式に値がない場合はnilを使用します)。最後の式のすべての値は式リストの値に含まれます。
四則演算子[]
Luaは一般的な算術演算子をサポートしている。加算、減算、乗算、除算、剰余、累乗、および単項の符号反転。もしオペランドが数値、あるいは数値に変換できる文字列 (tonumber()を参照) なら、すべての演算は通常の意味を持つ。
いずれかのオペランドが適切なメタメソッドを持つテーブルである場合、そのメタメソッドが呼び出される。
記号 | 関数 | 例文法 | メタ関数 | Notes |
---|---|---|---|---|
+ | 加算 | a + b | __add | |
- | 減算 | a - b | __sub | |
* | 乗算 | a * b | __mul | |
/ | 除算 | a / b | __div | 0で割ってもタイムワープやエラーは起こらず、Nanかinfを返す |
% | 余り | a % b | __mod | 定義はa % b == a - math.floor( a / b ) * b
|
^ | 累乗 | a ^ b | __pow | 任意の指数に対して動作する。 |
- | 負の数 | -a | __unm |
関係演算子[]
Luaの関係演算子は==
、~=
、<
、>
、<=
、そして>=
です。関係演算子の結果は常にブール値です。
等式 (==
) はまずそのオペランドの型を比較します。それらが異なる場合、結果は偽です。次に、値を比較します。nil、boolean、number、およびstringは、期待どおりに比較されます。関数がまったく同じ関数オブジェクトを参照する場合、それらの関数は同等です。function() end == function() end
は、2つの異なる無名関数を比較しているため、falseを返します。テーブルは通常同じ方法で比較されますが、これは__eqメタメソッドを使って変更できます。
不等式(~=
)は、等式の厳密な否定です。
順序付け演算子の場合、両方が数値の場合、または両方とも文字列の場合は、直接比較されます。次に、メタメソッドがチェックされます:
a < b
は __ltを使用しますa <= b
は __leの使用を優先し、その次に__ltがあるならnot ( b < a )
として使用しますa > b
はb < a
として使用しますa >= b
はb <= a
として使用します
必要なメタメソッドが利用できない場合は、エラーが発生します。
論理演算子[]
Luaの論理演算子はand
、or
とnot
の3つ。制御構造と同じく、すべての論理演算子は false と nil の両方を偽、それ以外のすべてを真とみなす。
- 論理積演算子
and
は、最初の引数が false か nil ならその値を返し、そうでなければ二番目の引数を返す。 - 論理和演算子
or
は最初の引数が false か nil 以外ならその値を返し、そうでなければ二番目の引数を返す。 - 否定演算子
not
は常に false か true を返す。
and と or は共にショートカット評価を行う。 つまり、二番目のオペランドは、それが必要なときだけ評価される。たとえば、foo() or bar()
は、foo()
がfalseまたはnilの場合にのみbar()
を呼び出す。
結合演算子[]
Luaの文字列連結演算子はふたつのドット(a .. b
)で表す。もし両方のオペランドが文字列か数値なら、それらは一定のルールに従って文字列に変換される。そうでなければ、"concat"メタメソッドが呼ばれる。
Luaの文字列は不変であり、Luaはいかなる種類の "文字列ビルダー"も提供していないので、a = a .. b
を繰り返し実行するループが必要になりる。(繰り返しごとに新しい文字列を作成し、最終的に古い文字列をガベージコレクションするやつ。)多くの文字列を連結する必要がある場合は、string.format()を使用するか、すべての文字列をシーケンス に挿入して最後にtable.concat()を使用する方が速い場合があるとか。
長さ演算子[]
長さ演算子は単項演算子#
で表される。文字列の長さはそのバイト数である(つまり、各文字が1バイトだとした場合の、文字列の長さである)。
テーブルt
の長さは、t[n]
がnil
でなくt[n+1]
がnil
であるような整数n
と定義されている。また、t[1]
がnil
ならn
はゼロになりうる。nil
でない値が1からn
まで格納されている普通の配列では、 その長さは最後のインデックスn
を正しく返す。
配列に「穴」がある場合(つまり間にnil
がある場合)、#t
はどれかのnil
のひとつ前を返すかもしれない(つまり、そのnil
が配列の終わりであるように見えるのだ)。
-- 穴のあいた配列
a = { 1, 2, nil, 4 }
-- This may output either 2 or 4.
-- And this may change even if the table is not modified.
mw.log( #a )
演算子の優先順位[]
Luaでの演算子の優先順位を以下に示す。優先順位は高い方から順に
- ^
- not # - (負の数)
- * / %
- + - (減算)
- ..
- < > <= >= ~= ==
- and
- or
普段通りに、カッコを使って式の優先順位を変えることができる。 連結 (`..´) と累乗 (`^´) は右結合である。つまり、a^b^c
はa^(b^c)
として解釈される。他の二項演算子はすべて左結合である。つまり、a+b+c
は(a+b)+c
と解釈される。
関数呼び出し[]
Luaの関数呼び出しには以下の構文が使える。
func( exp-list )
Luaの式リストでは通常行われているように、リストの最後の式は複数の引数値を指定できる。
関数定義内に引数があるよりも少ない数の値で式リスト内で関数が呼び出された場合、追加の引数はnil値になる。式リストに引数よりも多くの値が含まれている場合、余分な値は破棄される。関数が可変数の引数を取ることも可能なのだ。詳細は関数の定義を参照。
Luaでは、関数の戻り値、つまりfunc()()
を直接呼び出すこともできる。呼び出される関数を決定するために変数アクセスよりも複雑な式が必要な場合は、変数アクセスの代わりに括弧で囲まれた式を使用することができるのだ。
Luaの関数呼び出しは糖衣構文(シンタックスシュガー)を使う事もできる。主にテーブル自身をテーブルライブラリで使ったり、メタテーブルを呼び出す時に使う。
例えば、
table:name( exp-list )
と表記する。これは
table.name( table, exp-list )
のシンタックスシュガーであり、 table の評価がただ一度である点だけが異なる。
引数がその場で定義されたテーブル1つや文字列1つであれば、このような表記ができる。
func{ arg1 = exp, arg2 = exp } func"string"
これは以下の表記のシンタックスシュガーとも言える。
func( { arg1 = exp, arg2 = exp } ) func( "string" )
両方使った場合はこのような違いが現れる。
table:name{ arg1 = ''exp'', arg2 = ''exp'' }
table.name( table, { arg1 = ''exp'', arg2 = ''exp'' } )
関数の定義[]
関数定義の構文を以下に示す。
function ( var-list ) block end
All variables in var-list are local to the function, with values assigned from the expression list in the function call. Additional local variables may be declared inside the block.
関数定義は実行可能な式であり、関数型の値を持つ。同じ関数の異なるインスタンスは異なるローカル変数と異なる環境テーブルを参照する場合がある。
When the function is called, the statements in block are executed after local variables corresponding to var-list are created and assigned values. 関数の結果を返すには return 文を使う。return文に出会わずに制御が関数の終わりまで達したら、関数は何も返さない。
Luaがチャンクをコンパイルすると、その中にある関数の本体もコンパイルされる。そして、Luaが関数定義を実行したとき、関数は インスタンス化(またはクローズ) される。この関数インスタンス(またはクロージャ) は式の最終的な値である。 例えば、
-- This returns a function that adds a number to its argument
function makeAdder( n )
return function( x )
-- The variable n from the outer scope is available here to be added to x
return x + n
end
end
local add5 = makeAdder( 5 )
mw.log( add5( 6 ) )
-- prints 11
A function may be declared to accept a variable number of arguments, by specifying ...
as the final item in the var-list:
function ( var-list, ... ) block end
Within the block, the varargs expression ...
may be used, with the result being all the extra values in the function call. 例えば、
local join = function ( separator, ... ) -- get the extra arguments as a table local args = { ... } -- get the count of extra arguments, correctly local n = select( '#', ... ) return table.concat( args, separator, 1, n ) end join( ', ', 'foo', 'bar', 'baz' ) -- returns the string "foo, bar, baz"
The select() function is designed to work with the varargs expression; in particular, select( '#', ... )
should be used instead of #{ ... }
to count the number of values in the varargs expression.
Lua provides syntactic sugar to combine function declaration and assignment to a variable; see Function declaration statements for details.
これは機能しないことに注意:
local factorial = function ( n )
if n <= 2 then
return n
else
return n * factorial( n - 1 )
end
end
関数宣言はローカル変数代入文が完了する前に処理されるので、関数本体内の "factorial"はその名前の(おそらく未定義の)大域変数を参照する。この問題は、最初にローカル変数を宣言してから次のステートメントで代入するか、関数宣言ステートメント構文を使用することで回避できるぞ。