この初版は Lua 5.0 向けに記述されました。以降のバージョンでも依然としておおよそ関連していますが、一部相違があります。
第 4 版は Lua 5.3 を対象としており、Amazon やその他の書店で購入できます。
本を購入することで、Lua プロジェクトのサポートにも協力できます。


5 – 関数

関数は、Lua でのステートメントと式を抽象化する主要なメカニズムです。関数は具体的なタスクを実行することも(他の言語では、これらはプロシージャやサブルーチンと呼ばれることがあります)、値を計算して返したりすることもできます。最初のケースでは、関数呼び出しをステートメントとして使用します。2 番目のケースでは、式として使用します

    print(8*9, 9/8)
    a = math.sin(3) + math.cos(10)
    print(os.date())
どちらのケースでも、括弧内に囲まれた引数のリストを記述します。関数呼び出しに引数がない場合は、呼び出しを示す空のリスト () を記述する必要があります。このルールには例外が 1 つあります。関数が単一引数しか持っておらず、その引数がリテラル文字列またはテーブルコンストラクタである場合、括弧は省略可能です
    print "Hello World"     <-->     print("Hello World")
    dofile 'a.lua'          <-->     dofile ('a.lua')
    print [[a multi-line    <-->     print([[a multi-line
     message]]                        message]])
    f{x=10, y=20}           <-->     f({x=10, y=20})
    type{}                  <-->     type({})

Lua では、オブジェクト指向呼び出しのための特殊構文であるコロン演算子も提供されています。 o:foo(x) などの式は、 o.foo(o, x) と記述する別の方法にすぎません。つまり、 o.foo を呼び出し、 o を最初の追加引数として追加することになります。第 16 章では、このような呼び出し(およびオブジェクト指向プログラミング)について、詳しく説明します。

Lua プログラムによって使用される関数は、Lua と C(またはホストアプリケーションで使用される他の言語)の両方で定義できます。たとえば、すべてのライブラリ関数は C で記述されていますが、この事実は Lua プログラマーと無関係です。関数を呼び出すとき、Lua で定義された関数と C で定義された関数に違いはありません。

他の例で見たように、関数定義には決まった構文があります。たとえば

    -- add all elements of array `a'
    function add (a)
      local sum = 0
      for i,v in ipairs(a) do
        sum = sum + v
      end
      return sum
    end
その構文では、関数定義には 名前(前の例では add)、パラメータのリスト、ステートメントのリストである 本体があります。

パラメーターは、関数呼び出しで渡される実際の実引数で初期化されて、まったく局所変数と同じように機能します。引数の数が、パラメーターの数と異なる関数呼び出しをすることができます。Lua は、多重代入のように、引数の数をパラメーターの数に調整します。余った引数が削除され、余ったパラメーターはnil になります。たとえば、以下のような関数があるとします。

    function f(a, b) return a or b end
引数からパラメーターへの、以下のマッピングになります。
    CALL             PARAMETERS
       
    f(3)             a=3, b=nil
    f(3, 4)          a=3, b=4
    f(3, 4, 5)       a=3, b=4   (5 is discarded)
この動作はプログラミングエラー (ランタイムで簡単に検出できます) になる可能性がありますが、とりわけ、初期引数に役立ちます。たとえば、次の関数を考えてみましょう。グローバルカウンターを増分します。
    function incCount (n)
      n = n or 1
      count = count + n
    end
この関数の初期引数は 1 です。つまり、incCount() の呼び出しには、引数がない場合、count は 1 増分されます。incCount() を呼び出すと、Lua はまず nnil で初期化します。or の結果は、その 2 番目のオペランドです。その結果、Lua は 1 を n の初期値として代入します。