この第 1 版は Lua 5.0 向けに書かれました。後のバージョンでもほとんど内容に違いはありませんが、いくつかの差異があります。
第 4 版は Lua 5.3 をターゲットとしており、Amazon やその他の書店で購入できます。
この本を購入することで、Lua プロジェクトのサポートにも協力していただけます。


8.3 – エラー

人間は過ちを犯す生き物。したがって、エラーを最善の方法で処理する必要があります。Lua は拡張言語であり、多くの場合、アプリケーションに埋め込まれるため、エラーが発生すると単にクラッシュしたり終了したりすることはできません。その代わり、エラーが発生するたびに、Lua は現在のチャンクを終了し、アプリケーションに戻ります。

Lua が遭遇する予期しない条件はすべて、エラーを引き起こします。数値ではない値の加算、関数ではない値の呼び出し、テーブルではない値のインデックス指定などを試行するとエラーが発生します。(後述のように、メタテーブルを使用してこの動作を変更できます。)また、error 関数を呼び出すことで明示的にエラーを発生させることもできます。その引数はエラーメッセージです。通常、この関数はコード内のエラーを処理するための適切な方法です

    print "enter a number:"
    n = io.read("*number")
    if not n then error("invalid input") end
if not ... then error end のような組み合わせは非常に一般的であるため、Lua には assert というそのジョブ専用の組み込み関数があります。
    print "enter a number:"
    n = assert(io.read("*number"), "invalid input")
assert 関数は、最初の引数が偽でないかどうかを確認し、単にその引数を返します。引数が偽の場合(つまり false または nil)、assert はエラーを発生させます。2 番目の引数のメッセージはオプションなので、エラーメッセージで何も言いたくない場合はその必要はありません。ただし、assert は通常の関数であることに注意してください。それゆえ、Lua は関数を呼び出す前に常に引数を評価します。したがって、次のようなものがあるとします。
    n = io.read()
    assert(tonumber(n),
           "invalid input: " .. n .. " is not a number")
n が数値の場合でも、Lua は常に連結を実行します。このような場合は、明示的なテストを使用する方が賢明です。

関数が予期しない状況(例外)を見つけた場合、2 つの基本的な動作を想定できます。それはエラーコード(通常は nil)を返すか、error 関数を呼び出してエラーを発生させることができます。これらの 2 つのオプションを選択するための決まりはありませんが、一般的なガイドラインを示すことができます。簡単に回避できる例外はエラーを発生させるべきですが、それ以外の場合はエラーコードを返す必要があります。

例えば、sin 関数を考えてみましょう。テーブルで呼び出された場合、どのように動作する必要がありますか?エラーコードを返すとします。エラーをチェックする必要がある場合は、次のように記述する必要があります。

    local res = math.sin(x)
    if not res then     -- error
      ...
ただし、関数を呼び出す前にこの例外を容易にチェックできます。
    if not tonumber(x) then     -- error: x is not a number
      ...
ただし、通常は sin の引数も結果もチェックしません。引数が数値でない場合、おそらくプログラムに何か問題があることを意味します。このような状況では、計算を停止してエラーメッセージを発行するのが、例外を処理するための最も簡単で実用的な方法です。

それに対し、ファイルを開く io.open 関数について考えてみましょう。存在しないファイルをよみこもうとした場合、関数はどのように動作すべきでしょうか? この場合、関数をよびだすまえに例外をチェックする簡単な方法は存在しません。多くのシステムでは、ファイルが存在するかを確認する唯一の方法は、ファイルを開こうとすることです。したがって、 io.open が外部的な理由(例えば "ファイルが存在しません""アクセスが拒否されました")によりファイルをひらけない場合、nilと、エラーメッセージを含む文字列が返されます。この方法を使うことで、たとえばユーザーに別のファイル名を入力させることによって、状況を適切に処理する機会を得ることができます

    local file, msg
    repeat
      print "enter a file name:"
      local name = io.read()
      if not name then return end   -- no input
      file, msg = io.open(name, "r")
      if not file then print(msg) end
    until file
このような状況に対処したくないのであれば、でも安全側にいたいというのであれば、単に assert を使って操作を保護してください
    file = assert(io.open(name, "r"))
これは典型的なLuaの慣用句です: io.open が失敗すると、 assert はエラーを出すことになります。
    file = assert(io.open("no-file", "r"))
      --> stdin:1: no-file: No such file or directory
io.open からの2番目の結果であるエラーメッセージが、 assert への2番目の引数になることに注意してください。