この初版は Lua 5.0 向けに書かれました。以後のバージョンでも多くの部分が関連性がありますが、いくつか違いがあります。
第 4 版は Lua 5.3 を対象としており、Amazon などの書店で購入できます。
この本を購入することで、Lua プロジェクトをサポートできます。


27.1 – 配列操作

Lua での「配列」は、特定の方法で使用されるテーブルの名前です。配列は、テーブルの操作に使用する同じ関数 (lua_settablelua_gettable) を使用して操作できます。ただし、経済性と簡潔性という Lua の一般的な考え方とは逆に、API には配列操作用の特別な関数が用意されています。これはパフォーマンス上の理由です。この操作は、アルゴリズムの内部ループ (ソートなど) で頻発するので、この操作が速くなることで、関数の全体のパフォーマンスが大幅に向上する場合があります。

API で提供される配列操作用の関数は次のとおりです。

    void lua_rawgeti (lua_State *L, int index, int key);
    void lua_rawseti (lua_State *L, int index, int key);
lua_rawgetilua_rawseti の説明は少し混乱する可能性があります。これは 2 つのインデックスを使用するからです。index はスタック内のテーブルの位置を表し、key はテーブル内の要素の位置を表します。lua_rawgeti(L, t, key) の呼び出しは、次のシーケンスと同等です。
    lua_pushnumber(L, key);
    lua_rawget(L, t);
t が正数の場合です (そうでない場合は、スタックの新しい項目を補正する必要があります)。lua_rawseti(L, t, key) の呼び出し (t が正数の場合) は次のとおりです。
    lua_pushnumber(L, key);
    lua_insert(L, -2);  /* put `key' below previous value */
    lua_rawset(L, t);
どちらの関数も、単純操作を使用することに注意してください。これらは高速で、配列として使用されるテーブルは、メタメソッドをほとんど使用しません。

これらの関数の使用例については、前の l_dir 関数のループ本体を以下のように書き換えることができます。

        lua_pushnumber(L, i++);  /* key */
        lua_pushstring(L, entry->d_name);  /* value */
        lua_settable(L, -3);
次のように。
        lua_pushstring(L, entry->d_name);  /* value */
        lua_rawseti(L, -2, i++);  /* set table at key `i' */

より完全な例として、次のコードではマップ関数が実装されています。与えられた関数を配列のすべての要素に適用し、各要素を呼び出しの結果に置き換えます。

    int l_map (lua_State *L) {
      int i, n;
    
      /* 1st argument must be a table (t) */
      luaL_checktype(L, 1, LUA_TTABLE);
    
      /* 2nd argument must be a function (f) */
      luaL_checktype(L, 2, LUA_TFUNCTION);
    
      n = luaL_getn(L, 1);  /* get size of table */
    
      for (i=1; i<=n; i++) {
        lua_pushvalue(L, 2);   /* push f */
        lua_rawgeti(L, 1, i);  /* push t[i] */
        lua_call(L, 1, 1);     /* call f(t[i]) */
        lua_rawseti(L, 1, i);  /* t[i] = result */
      }
    
      return 0;  /* no results */
    }
この例では 3 つの新しい関数が導入されています。luaL_checktype 関数 (lauxlib.h から) は、指定された引数が指定された型であることを確認します。そうでない場合は、エラーを発生させます。luaL_getn 関数は、指定されたインデックスの配列のサイズを取得します (table.getn はそのジョブを実行するために luaL_getn を呼び出します)。lua_call 関数は、保護されていない呼び出しを行います。lua_pcall と似ていますが、エラーが発生した場合はエラーコードを返すのではなく、エラーをスローします。アプリケーションでメインコードを記述している場合は、エラーをキャッチしたいので、lua_call は使用しないでください。ただし、関数を記述している場合は、通常 lua_call を使用することが適切です。エラーが発生した場合は、誰かがそのエラーに対処できるようにそのままにしておきます。