この第 1 版は Lua 5.0 向けに書かれました。後バージョンの大部分は依然としてこの版に関連がありますが、違いはいくつかあります。
第 4 版は Lua 5.3 を対象としており、Amazon やその他の書店でご購入いただけます。
本を購入することにより、Lua プロジェクトのサポートにもご協力いただけます。


6.2 – グローバルではない関数

ファーストクラス関数の明白な結果は、グローバル変数だけでなく、テーブルフィールドとローカル変数に機能を保存できることです。

既に、テーブルフィールドの関数の例をいくつか見てきました。ほとんどの Lua ライブラリはこのメカニズムを使用します(例: io.readmath.sin)。Lua でこのような関数を作成するには、関数とテーブルの通常の構文をまとめるだけで十分です

    Lib = {}
    Lib.foo = function (x,y) return x + y end
    Lib.goo = function (x,y) return x - y end
もちろん、コンストラクターも使用できます
    Lib = {
      foo = function (x,y) return x + y end,
      goo = function (x,y) return x - y end
    }
さらに、Lua はこれらの関数を定義するための他の構文も提供しています
    Lib = {}
    function Lib.foo (x,y)
      return x + y
    end
    function Lib.goo (x,y)
      return x - y
    end
この最後のフラグメントは、最初の例とまったく同じです。

関数をローカル変数に保存すると、ローカル関数、つまり、特定のスコープに限定された関数になります。このような定義は特にパッケージに役立ちます。Lua は各チャンクを関数として処理するため、チャンクはチャンクの内部からしか見えないローカル関数を宣言できます。字句スコープにより、パッケージ内の他の関数がこれらのローカル関数を使用できるようになります

    local f = function (...)
      ...
    end
    
    local g = function (...)
      ...
      f()   -- external local `f' is visible here
      ...
    end
Lua はこれらのローカル関数の使用を、シンタックスシュガーでサポートしています
    local function f (...)
      ...
    end

再帰ローカル関数の定義において、微妙な問題が発生します。ナイーブなアプローチはここで機能しません

    local fact = function (n)
      if n == 0 then return 1
      else return n*fact(n-1)   -- buggy
      end
    end
Lua が関数本体でコール fact(n-1) をコンパイルすると、ローカルの fact はまだ定義されていません。したがって、その表現はローカルの fact ではなく、グローバルの fact をコールします。この問題を解決するには、まずローカル変数を定義してから関数を定義する必要があります
    local fact
    fact = function (n)
      if n == 0 then return 1
      else return n*fact(n-1)
      end
    end
これで関数の fact はローカル変数を参照します。関数が定義されたときのその値は関係ありません。関数が実行されたときまでに、fact は既に正しい値を持っています。これは Lua がローカル関数用のシンタックスシュガーを展開する方法なので、再帰関数でも気にせず使用できます
    local function fact (n)
      if n == 0 then return 1
      else return n*fact(n-1)
      end
    end
もちろん、間接再帰関数を使用する場合、この手法は機能しません。このような場合は、明示的な先読み宣言と同等のものを使用する必要があります
    local f, g    -- `forward' declarations
    
    function g ()
      ...  f() ...
    end
    
    function f ()
      ...  g() ...
    end