Lua/式

先に説明したように、式は値を持ち、評価することができるコードの断片です。直接実行することはできないので(関数呼出しは例外)、式からなる次のようなコードだけを含むスクリプトは誤りとなる。
コードは一連の文で構成されていなければなりません。これらの文には、文が命令を実行するために操作または使用しなければならない値である式を含めることができます。
本章のコード例の中には、式だけで構成されているものがあり、有効なコードとは言えません。次章では、文を取り上げ、有効なコードを書き始めることができるようにします。
式を評価することは、その値を求めるために計算することです。 ある式が評価する値は、環境やスタックレベルに依存するため、あるコンテキストから別のコンテキストに変更される可能性があります。 この値は、あるときは数値であり、あるときはテキストであり、またあるときは他の多くのデータ型のいずれかである。
Luaや一般的なプログラミングでは、式は通常、1つ以上の値と0個以上の演算子で構成されます。演算子の中には、特定の型にしか使えないものがあります(例えば、テキストを除算するのは非論理的ですが、数字を除算するのは理にかなっています)。演算子には、単項演算子と二項演算子の2種類があります。単項演算子は、1つの値しかとらない演算子である。たとえば、単項マイナス演算子(-)は、-5, -3, -6, などの1つの数値のみをパラメータとして受け取ります。単項マイナス演算子は、1つの数値をパラメータとして受け取り、その数値を否定します(符号を反転した値を返すという意味)。しかし、異なる演算子の二項マイナス演算子(-)は、2つの値を取り、最初の値から2番目の値を引きます:5 - 3、8 - 6、4 - 9、など。
type関数で数値の型を文字列として得ることができる。
数字は一般的に数量を表しますが、それ以外にも様々なことに利用できます。Luaの数値型は、ほとんど実数と同じように動作します。数値は整数、10進数、10進指数、さらにはw:16進数で構成することができる。以下に有効な数をいくつか示します。
Luaで数値を扱う演算子は以下の通りです。
これらの演算子(数学の基本的な演算子と同じです)は、最後の演算子を除いて、すでにご存知でしょう。最後の演算子はモジュロ演算子と呼ばれ、ある数を別の数で割った余りを計算するものです。例えば、5 % 3 の場合、5 を 3 で割った余りが 2 なので、結果は 2 となります。モジュロ演算子は、他の演算子よりも一般的ではありませんが、複数の用途があります。
整数は数値型のサブタイプです。 整数は Lua5.3で追加されました。 数値型は、整数か浮動小数点数です。 浮動小数点数は前述の整数と似ていますが、整数は小数点以下の部分がない数字です。 浮動小数点数の除算 (/) と指数演算はオペランドを常に結果は浮動小数点数に変換し、それ以外の演算子はオペランドが整数の場合整数を与えます。 それ以外の場合、整数除算演算子 (//) を除いて、結果は浮動小数点数になります。
Nilは値nilの型であり、その主な特性は他のどの値とも異なることです。通常、有用な値がないことを表す。値nilを持つものの例をいくつか挙げます。
さらに高度なことを言えば、意図的にnil値を代入することで、変数やテーブルへの参照を取り除き、ガベージコレクタにメモリを再利用させることができます。
論理型の値はtrueかfalseのどちらかであり、それ以外はありえません。 これはLuaではキーワードであるtrueとfalseで表記されます。 重要なのは、nilは前述したように異なるデータ型であることです。
and、or、not()は通常論理型に関連しますが、Luaではどのデータ型にも使用できます。
基本的に、not演算子は論理値を否定するだけであり(trueの場合はfalseになり、falseの場合はtrueになります)、and演算子は両方がtrueの場合にtrueを返します。 そうでない場合はtrueとfalseを返し、引数のいずれかがtrueの場合はor演算子がtrueを返し、それ以外の場合はfalseを返します。しかし、これは正確な仕組みではなく、正確な仕組みは上の表で説明したとおりです。Luaでは、論理式では値falseとnilは両方ともfalseと見なされますが、他のすべてはtrueと見なされます(0と空の文字列も)。
次の章で紹介する関係演算子(<, >, <=, >=, ~=, ==)は、必ずしも論理値をオペランドとして受け取る必要はありません
これは調整が難しい場合があります。わかりやすくするために、ここにいくつかの真理値表または式と結果の組合せを示します。 ここで、xはnil、true、またはfalseになります。
これは、やや直感に反して、次のことを意味します。
さらに
文字列(Strings)とは、テキストを表現するために使用できる文字の並びのことです。Luaでは二重引用符、一重引用符、大括弧([ ])で囲んで記述します。 このことは以前コメントについてのセクションで取り上げました(なお、コメントと文字列には、大括弧で区切れること以外に共通点はなく、コメントの場合はハイフン2つで始まります)。大括弧で囲まれていない文字列は、1行分しか続きません。 このため、大括弧を使わずに何行も続く文字列を作るには、エスケープシーケンスを使うしかありません。 これは、場合によっては一重引用符(')や二重引用符(")を挿入する唯一の方法でもあります。 エスケープシーケンスには、エスケープ文字(Luaでは常にバックスラッシュ(' \'))と、エスケープする文字を識別するための識別子の2つが含まれます。
エスケープシーケンスは、文字を文字列に直接入れると問題が発生する場合に使用されます。たとえば、二重引用符で囲まれたテキスト文字列があり、二重引用符を含める必要がある場合は、文字列を別の文字で囲むか、二重引用符をエスケープする必要があります。大括弧で区切られた文字列内の文字をエスケープする必要はありません。これはすべての文字に当てはまります。大括弧で区切られた文字列内のすべての文字は、そのまま使用されます。%文字は、文字列パターン(string patterns)で魔法の文字をエスケープするために使用されますが、「エスケープ」という用語は別のコンテキストで使用されます。
便宜上、文字列の先頭の長い括弧の直後に改行がある場合、その改行は無視される。したがって,次の2つの文字列は等価である。
文字列の長さを数値として得るには、単項の長さ演算子('#')を使用します。
形式言語理論やコンピュータプログラミングにおいて、文字列の連結は2つの文字列を端から端まで結合する操作である。例えば、"snow" と "ball" を連結すると "snowball" となる。
-- Wikipedia : Concatenation
Luaの文字列連結演算子はドット2つ('..')で表されます。以下は、"snow" と "ball" を連結し、結果を表示する連結の例です。
Luaの4つの基本型(数値、論理型、nil、文字列)については前項までで説明しましたが、関数、テーブル、ユーザーデーター、スレッドの4つの型が抜けています。関数は、呼出したり、値を受け取ったり、値を返したりすることができるコードの断片のことです。テーブルは、データ操作に使用できるデータ構造です。ユーザーデーターは、Luaが組込まれたアプリケーションの内部で使用され、アプリケーションが制御するオブジェクトを介してLuaとそのプログラムが通信できるようにします。最後にスレッドですが、これはコルーチンによって使用され、多くの関数を同時に実行することができます。これらは全て後述しますので、他のデーター型があることだけは覚えておいてください。
リテラル(Literals)は、ソースコードで固定値を表すための表記です。スレッドとユーザーデーターを除くすべての値は、Luaではリテラルとして表すことができます。たとえば、文字列リテラル(文字列に評価されるリテラル)は、文字列が表す必要のあるテキストを一重引用符、二重引用符、または大括弧で囲んで構成します。一方、数値リテラルは、10進表記(例:12.43)、科学的記数法(例:3.1416e-2 と 0.31416E1)または16進表記(例:0xff)を使用して表現された数値で構成されます。
型強制(Coercion)とは、あるデータ型の値を別のデータ型の値に変換することです。Luaでは、文字列と数値の間に自動的に強制型変換が行われます。文字列に算術演算を施すと、この文字列を数値に変換しようとします。逆に、文字列を想定していたのに数値が使われた場合、その数値は文字列に変換されます。これはLuaの演算子にも、デフォルト関数(言語が提供する関数)にも当てはまります。
数値から文字列、文字列から数値への強制変換は、tostring関数とtonumber関数を用いて手動で行うことも可能です。前者は引数として数値を受け取ってそれを文字列に変換し、後者は引数として文字列を受け取ってそれを数値に変換します(第2引数にはデフォルトの10進数とは異なる基数を任意で与えることができます)。
Lua 5.3以降、2進数(ビットパターン)を操作するためのビット演算子が用意されています。これらの演算子は、他の演算子ほど頻繁に使用されるものではないので、必要ない場合はこのセクションを読み飛ばしてもかまいません。
Luaのビット演算子は、常に整数を対象とし、必要な場合はオペランドを変換します。また、整数を与えることもできます。
ビット単位のAND演算(演算子&を使用)は、同じ長さの2つのバイナリ表現のビットの各ペアに対して論理積を実行します。 たとえば、5 & 3 は1と評価されます。これは、これらの数値の2進表現を見ると説明できます(下付き文字は基数を表すために使用されます)。
( 5 ) 10 = ( 0101 ) 2 {\displaystyle (5)_{10}=(0101)_{2}}
( 3 ) 10 = ( 0011 ) 2 {\displaystyle (3)_{10}=(0011)_{2}}
( 1 ) 10 = ( 0001 ) 2 {\displaystyle (1)_{10}=(0001)_{2}}
5と3の2進数表現において、ある位置のビットが1であれば(最後のビットのように)、その位置のビットは結果的に1となり、それ以外の場合は0となります。
ビット単位のOR演算(演算子|を使用)は、ビット単位のANDと同じように機能し、論理積を実行する代わりに論理和を実行します。 したがって、5 | 3は7と評価されます:
( 5 ) 10 = ( 0101 ) 2 {\displaystyle (5)_{10}=(0101)_{2}}
( 3 ) 10 = ( 0011 ) 2 {\displaystyle (3)_{10}=(0011)_{2}}
( 7 ) 10 = ( 0111 ) 2 {\displaystyle (7)_{10}=(0111)_{2}}
ここで、最終結果の各位置のビットが0になるのは、2つのオペランドの2進表現がその位置に0ビットを持つときだけであることがわかります。
ビット単位のXOR演算(演算子~を使用)は他の2つの演算と同じように機能しますが、特定の位置では、ビットの1つであり、両方ではない場合、最後のビットは1つだけです。 オペランドは1です(排他的論理和や論理不一致と呼ばれる演算です)。
( 5 ) 10 = ( 0101 ) 2 {\displaystyle (5)_{10}=(0101)_{2}}
( 3 ) 10 = ( 0011 ) 2 {\displaystyle (3)_{10}=(0011)_{2}}
( 6 ) 10 = ( 0110 ) 2 {\displaystyle (6)_{10}=(0110)_{2}}
これは前の例と同じですが、両方のオペランドの最後のビットが1であったため、結果の最後のビットが1ではなく0であることがわかります。
ビット単位のNOT</ dfn>演算(演算子 ~ を使用)は、一意のオペランドの各ビットに対して論理否定を実行します。つまり、各0が1になり、各1が0になります。 ~7 は-8と評価されます:
( 7 ) 10 = ( 0111 ) 2 {\displaystyle (7)_{10}=(0111)_{2}}
( 8 ) 10 = ( 1000 ) 2 {\displaystyle (8)_{10}=(1000)_{2}}
ここでは、オペランドで0だったため、結果の最初のビットが1になり、他のビットはすべて1だったため0になりました。

これらのビット演算子に加えて、Lua5.3は算術ビットシフトもサポートしています。 左シフトは、演算子<<を使用し、左側に示されています。これは、すべてのビットを、第2オペランドに対応するビット数だけ左にシフトすることで構成されます。 右シフトは、演算子>>で示され、右に示されていますが、同じように動作しますが、方向が逆になります。
演算子の優先順位は、Luaでも一般的な数学と同じように機能します。ある演算子は他の演算子より先に評価され、括弧を使って演算の実行順序を任意に変更することができます。演算子が評価される優先順位は、以下のリストのように、優先順位の高いものから低いものへとなっています。これらの演算子の中には、まだ説明していないものもありますが、本書のどこかですべて取り上げる予定です。




1 What will print(type(type(5.2))) output?
2 What will the expression 0 or 8 return?


3 Which strings are valid?


4 Which expressions give the string "1223"?


5 True or false? not 5^3 == 5