まず、以下の関数を定義します。
function foo(a)
print("foo print",a)
return a
end
function goo(a)
print("goo print",a)
return a
end
function hoo(a)
print("hoo print",a)
return a
end
このコードを試してみてください:
フー
(hoo) (1979)
上記のプログラムをコンパイルして実行しようとすると、インタプリタは「'の近くは別の関数呼び出し文として、2行目は別の関数呼び出し文として、構文があいまいである」と報告します。しかし、foo(goo)は完全に合法な関数呼び出しの形式であり、foo(goo)は完全な関数呼び出し文になりうることを忘れないでください。 その場合、コンパイラーはプログラマーが本当に意図したことを知る術がありません。
コンパイルのプロセスをもう少し掘り下げると、Lua構文の正式な定義は以下のジェネレーターで構成されています:
stat -> functioncall
prefixexp -> functioncall
functioncall -> prefixexp args
| 名前 引数
ご覧のように、functioncallはstatまたはprefixexpのどちらかを指定することができますが、これは2つのジェネレータと競合しており、コンパイラはfoo(goo)にどちらを指定すればよいかわからないため、エラーが発生します。
この曖昧さの問題を解決するには、***行の後に文の区切りであるセミコロンを追加すれば、コンパイラはコードを2つの別々の文にコンパイルします。あるいは、2つの行を1つにまとめると、foo(goo)は完全な関数呼び出しとみなされます。
実は、曖昧さを引き起こす可能性のある状況が他にも3つあります:
-- prefixexp -> functioncall これは言語設計のある種の妥協点だ。
-- exp -> functioncall これは言語設計のある種の妥協である。
-- コンパイラーは、fooを式として解釈するのか接頭辞として解釈するのかわからない。
local v = foo(goo)
-- exp -> var 同じことが prefixexp -> var コンフリクト
-- 2行目の変数mは、式として扱うべきか接頭辞として扱うべきかはっきりしない。
m = foo local v = m
-- prefixexp -> '(' exp ')' 与
-- exp -> '(' exp ')' コンフリクト
-- (t)に何を入れたらいいのかわからない。.fn)式または接頭辞を参照のこと。
t = {fn = foo} local v = (t.fn)
の例の曖昧さを解決するための同じ2つのアプローチが、3つのケースすべてに当てはまります。この時点で、曖昧さの根本的な原因は、Luaステートメント間のセパレータが必須ではなくオプションであることにあることが容易に理解できます。C言語のように、各ステートメントの後にセミコロンを付けることが必須であれば、曖昧さは解消されるでしょう。しかし、多くの人はセミコロンという厄介な記号を入力することを好まないため、Luaの作者はプログラマー自身にその選択を委ねました。





