コンテンツにスキップ

Lua/式

出典: フリー教科書『ウィキブックス(Wikibooks)』
< Lua

これまでに説明したように、式は値を持ち、評価されるコードの断片です。式は直接実行されることはありません(関数呼び出しの例外を除く)、そのため、次のような式だけで構成されたスクリプトはエラーになります:

3 + 5
-- 上記のコードは、式だけしかを含んでいないのでエラーです。
-- コンピュータは '3 + 5' を実行できません。それは意味をなしません。

コードは一連の文の並びで構成されなければなりません。これらの文には、文が実行するために操作する値として使用される式が含まれることがあります。

この章のいくつかのコード例は有効なコードではありません。次の章では文について説明し、有効なコードの書き方を始めることができます。

[編集]

式を評価することは、その値を計算してその値を見つけることです。 特定の式が評価された場合の値は、環境やスタックレベルに依存することがあります。 この値は時々数値であり、時々テキストであり、他の多くのデータ型のいずれかであるため、「型がある」と言われています。

Luaでは、プログラミング全般で、式は通常、1つ以上の値と0個以上の演算子で構成されます。一部の演算子は特定の型としか使用できません(たとえば、テキストを除算しようとするのは不合理ですが、数値を除算することは合理的です)。演算子には2種類あります:単項演算子と二項演算子です。単項演算子は1つの値しか取りません。たとえば、単項の-演算子は、パラメータとして1つの数値を取ります: -5-3-6などです。これは1つの数値をパラメータとして取り、その数値を否定します(符号を反転した値を返すという意味)。一方、二項演算子の-は、二つの値を取り、最初の値から2番目の値を引きます:5 - 38 - 64 - 9などです。

値の型を文字列として取得することができます。これはtype関数を使用します:

print(type(32425)) --> number

数値

[編集]

数値は通常、量を表しますが、他にも多くの用途に使用できます。Luaの数値型は、ほとんどが実数と同様の方法で機能します。数値は整数、10進数、10進指数、または16進数として構築することができます。以下はいくつかの有効な数値の例です:

  • 3
  • 3.0
  • 3.1416
  • 314.16e-2
  • 0.31416E1
  • 0xff
  • 0x56

算術演算

[編集]

Luaの数値の演算子は次の通りです:

Luaの算術演算一覧
演算 文法 概要 結果
算術否定 -a a の符号を反転しその値を返す -3.14159 3.14159
加算 a + b ab の和を返す 5.2 + 3.6 8.8
減算 a - b a から b 差を返す 6.7 - 1.2 5.5
乗算 a * b ab の積を返す 3.2 * 1.5 4.8
指数関数 a ^ b ab乗、またはab の冪指数を返す 5 ^ 2 25
除算 a / b ab の商を返す 6.4 / 2 3.2
剰余 a % b ab の剰余を返す 5 % 3 2
整数除算 a // b ab の商を整数で返す 6.4 // 2 3

これらの演算子のうち、最後のもの以外は基本的な数学演算子と同じです。最後の演算子はモジュロ演算子と呼ばれ、単純に1つの数値を別の数値で割った余りを計算します。たとえば、5 % 3は、53で割った余りが2であるため、結果は2になります。このモジュロ演算子は他の演算子よりも一般的ではありませんが、複数の用途があります。

整数

[編集]

Lua 5.3で新しい数値のサブタイプ、整数が追加されました。数値は整数または浮動小数点数のいずれかになります。浮動小数点数は上記で説明した数値と同様ですが、整数は小数部を持たない数値です。浮動小数点の除算(/)と冪乗は常にオペランドを浮動小数点数に変換しますが、他のすべての演算子は、両方のオペランドが整数である場合には整数を返します。それ以外の場合は、床除算演算子(//)を除き、結果は浮動小数点数になります。

Nil型

[編集]

Nilは値nilの型であり、その主な特性は他のどの値とも異なることです。通常、有用な値がないことを表す。値nilを持つものの例をいくつか挙げます。

  • 値を代入する前にアクセスした変数の値
  • スコープ外の変数にアクセスしたときの値
  • 割当てられていないテーブルのキーの値
  • 文字列を数値に変換できない場合に tonumber が返す値

さらに高度なことを言えば、意図的にnil値を代入することで、変数やテーブルへの参照を取り除き、ガベージコレクタにメモリを再利用させることができます。

論理型

[編集]

論理型の値はtruefalseのどちらかであり、それ以外はありえません。 これはLuaではキーワードであるtruefalseで表記されます。 重要なのは、nilは前述したように異なるデータ型であることです。

andornot()は通常論理型に関連しますが、Luaではどのデータ型にも使用できます。

Luaの論理演算子
演算 文法 概要
論理否定 not a もし a が false または nil ならば true を、それ以外ならば false を返す。
論理積 a and b もし afalse または nil ならば a を、それ以外ならば b を返す。
論理和 a or b もし afalse でも nil でもなければ a を、それ以外ならば b を返す。

基本的に、not演算子は論理値を否定するだけであり(trueの場合はfalseになり、falseの場合はtrueになります)、and演算子は両方がtrueの場合にtrueを返します。 そうでない場合はtruefalseを返し、引数のいずれかがtrueの場合はor演算子がtrueを返し、それ以外の場合はfalseを返します。しかし、これは正確な仕組みではなく、正確な仕組みは上の表で説明したとおりです。Luaでは、論理式では値falsenilは両方ともfalseと見なされますが、他のすべてはtrueと見なされます(0と空の文字列も)。

次の章で紹介する関係演算子(<, >, <=, >=, ~=, ==)は、必ずしも論理値をオペランドとして受け取る必要はありません

これは調整が難しい場合があります。わかりやすくするために、ここにいくつかの真理値表または式と結果の組合せを示します。 ここで、xniltrue、またはfalseになります。

論理演算と結果
結果
true and x x
false and x false
nil and x nil
true or x true
false or x x
nil or x x

これは、やや直感に反して、次のことを意味します。

論理積と偽値
結果
false and nil false
nil and false nil

さらに

偽値間の比較
結果
false == nil
nil == false
false
nil and false nil
論理否定
結果
not(false)
not(nil)
true
not(true) false

文字列

[編集]

文字列(Strings)とは、テキストを表現するために使用できる文字の並びのことです。Luaでは二重引用符、一重引用符、大括弧([ ])で囲んで記述します。 このことは以前コメントについてのセクションで取り上げました(なお、コメントと文字列には、大括弧で区切れること以外に共通点はなく、コメントの場合はハイフン2つで始まります)。大括弧で囲まれていない文字列は、1行分しか続きません。 このため、大括弧を使わずに何行も続く文字列を作るには、エスケープシーケンスを使うしかありません。 これは、場合によっては一重引用符(')や二重引用符(")を挿入する唯一の方法でもあります。 エスケープシーケンスには、エスケープ文字(Luaでは常にバックスラッシュ(' \'))と、エスケープする文字を識別するための識別子の2つが含まれます。

Lua のエスケープシーケンス
エスケープシーケンス 概要
\n 改行
\" 二重引用符
\' 一重引用符
\\ バックスラッシュ
\t 水平タブ
\### ### は 0 から 255 までの数字でなければなりません。結果は対応するASCII文字になります。

エスケープシーケンスは、文字を文字列に直接入れると問題が発生する場合に使用されます。たとえば、二重引用符で囲まれたテキスト文字列があり、二重引用符を含める必要がある場合は、文字列を別の文字で囲むか、二重引用符をエスケープする必要があります。大括弧で区切られた文字列内の文字をエスケープする必要はありません。これはすべての文字に当てはまります。大括弧で区切られた文字列内のすべての文字は、そのまま使用されます。%文字は、文字列パターン(string patterns)で魔法の文字をエスケープするために使用されますが、「エスケープ」という用語は別のコンテキストで使用されます。

"これは有効な文字列"

'これも有効な文字列'

"これは有効な \" 'エスケープされていない一重引用符とエスケープされた二重引用符を含む文字列"

[[
これは、複数の行に
続けることができます。

一重引用符、二重引用符、その他すべてを含むことができる(--コメントも含む)。
開いている大括弧と同じレベルの閉じる大括弧以外は(エスケープ文字も含めて)無視されます。
]]

"これは有効な文字列で、タブ \t, 二重引用符 \" そして バックスラッシュ \\ を含みます。"

"これは " は、途中にエスケープされていない二重引用符があるため、有効な文字列ではありません。"

便宜上、文字列の先頭の長い括弧の直後に改行がある場合、その改行は無視される。したがって,次の2つの文字列は等価である。

[[これは何行にもわたって
続く文字列です]]

[[
これは何行にもわたって
続く文字列です]]
-- 2番目の文字列の冒頭の長い括弧の直後には改行があるので、その改行は無視される。

文字列の長さを数値として得るには、単項の長さ演算子('#')を使用します。

print(#("This is a string")) --> 16

連結

[編集]

形式言語理論やコンピュータプログラミングにおいて、文字列の連結は2つの文字列を端から端まで結合する操作である。例えば、"snow" と "ball" を連結すると "snowball" となる。

-- Wikipedia : Concatenation

Luaの文字列連結演算子はドット2つ('..')で表されます。以下は、"snow" と "ball" を連結し、結果を表示する連結の例です。

print("snow" .. "ball") --> snowball
このコードは、"snow" と "ball" を連結し、その結果を表示します。

その他の型

[編集]

Luaの4つの基本型(数値、論理型、nil、文字列)については前項までで説明しましたが、関数、テーブル、ユーザーデータ、スレッドの4つの型が抜けています。関数は、呼出したり、値を受け取ったり、値を返したりすることができるコードの断片のことです。テーブルは、データ操作に使用できるデータ構造です。ユーザーデータは、Luaが組込まれたアプリケーションの内部で使用され、アプリケーションが制御するオブジェクトを介してLuaとそのプログラムが通信できるようにします。最後にスレッドですが、これはコルーチンによって使用され、多くの関数を同時に実行することができます。これらは全て後述しますので、他のデータ型があることだけは覚えておいてください。

リテラル

[編集]

リテラル(Literals)は、ソースコードで固定値を表すための表記です。スレッドとユーザーデータを除くすべての値は、Luaではリテラルとして表すことができます。たとえば、文字列リテラル(文字列に評価されるリテラル)は、文字列が表す必要のあるテキストを一重引用符、二重引用符、または大括弧で囲んで構成します。一方、数値リテラルは、10進表記(例:12.43)、科学的記数法(例:3.1416e-20.31416E1)または16進表記(例:0xff)を使用して表現された数値で構成されます。

型強制

[編集]

型強制(Coercion)とは、あるデータ型の値を別のデータ型の値に変換することです。Luaでは、文字列と数値の間に自動的に強制型変換が行われます。文字列に算術演算を施すと、この文字列を数値に変換しようとします。逆に、文字列を想定していたのに数値が使われた場合、その数値は文字列に変換されます。これはLuaの演算子にも、デフォルト関数(言語が提供する関数)にも当てはまります。

print("122" + 1) --> 123
print("The number is " .. 5 .. ".") --> The number is 5.

数値から文字列、文字列から数値への強制変換は、tostring関数とtonumber関数を用いて手動で行うことも可能です。前者は引数として数値を受け取ってそれを文字列に変換し、後者は引数として文字列を受け取ってそれを数値に変換します(第2引数にはデフォルトの10進数とは異なる基数を任意で与えることができます)。

ビット演算

[編集]

Lua 5.3以降、2進数(ビットパターン)を操作するためのビット演算子が用意されています。これらの演算子は、他の演算子ほど頻繁に使用されるものではないので、必要ない場合はこのセクションを読み飛ばしてもかまいません。

Luaのビット演算子は、常に整数を対象とし、必要な場合はオペランドを変換します。また、整数を与えることもできます。

ビット単位のAND演算(演算子&を使用)は、同じ長さの2つのバイナリ表現のビットの各ペアに対して論理積を実行します。 たとえば、5 & 3 は1と評価されます。これは、これらの数値の2進表現を見ると説明できます(下付き文字は基数を表すために使用されます)。

5と3の2進数表現において、ある位置のビットが1であれば(最後のビットのように)、その位置のビットは結果的に1となり、それ以外の場合は0となります。

ビット単位のOR演算(演算子|を使用)は、ビット単位のANDと同じように機能し、論理積を実行する代わりに論理和を実行します。 したがって、5 | 3は7と評価されます:

ここで、最終結果の各位置のビットが0になるのは、2つのオペランドの2進表現がその位置に0ビットを持つときだけであることがわかります。

ビット単位のXOR演算(演算子~を使用)は他の2つの演算と同じように機能しますが、特定の位置では、ビットの1つであり、両方ではない場合、最後のビットは1つだけです。 オペランドは1です(排他的論理和や論理不一致と呼ばれる演算です)。

これは前の例と同じですが、両方のオペランドの最後のビットが1であったため、結果の最後のビットが1ではなく0であることがわかります。

ビット単位のNOT</ dfn>演算(演算子 ~ を使用)は、一意のオペランドの各ビットに対して論理否定を実行します。つまり、各0が1になり、各1が0になります。 ~7 は-8と評価されます:

ここでは、オペランドで0だったため、結果の最初のビットが1になり、他のビットはすべて1だったため0になりました。

Left shiftRight shift

これらのビット演算子に加えて、Lua5.3は算術ビットシフトもサポートしています。 左シフトは、演算子<<を使用し、左側に示されています。これは、すべてのビットを、第2オペランドに対応するビット数だけ左にシフトすることで構成されます。 右シフトは、演算子>>で示され、右に示されていますが、同じように動作しますが、方向が逆になります。

演算子の優先順位

[編集]

演算子の優先順位は、Luaでも一般的な数学と同じように機能します。ある演算子は他の演算子より先に評価され、括弧を使って演算の実行順序を任意に変更することができます。演算子が評価される優先順位は、以下のリストのように、優先順位の高いものから低いものへとなっています。これらの演算子の中には、まだ説明していないものもありますが、本書のどこかですべて取り上げる予定です。


  1. 累乗: ^
  2. 単項演算: not, #, -, ~
  3. レベル2数学演算子: *, /, //, %
  4. レベル1数学演算子: +, -
  5. 連結: ..
  6. ビットシフト: <<, >>
  7. ビット単位のAND: &
  8. ビット単位のXOR: ~
  9. ビット単位のOR: |
  10. 関係演算子: <, >, <=, >=, ~=, ==
  11. 論理積: and
  12. 論理和: or

Quiz

[編集]

1 What will print(type(type(5.2))) output?

2 What will the expression 0 or 8 return?

true
false
0
8

3 Which strings are valid?

"test's test"
'test\'s test'
"test"s test"
'test"s test'
"test\'s test"
'test's test'

4 Which expressions give the string "1223"?

"122" + 3
"122" .. 3
"12" + "23"
12 .. 23

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

true
false