この初版は Lua 5.0 向けに書かれました。後続バージョンでも大部分は関連がありますが、いくつかの違いがあります。
第 4 版は Lua 5.3 をターゲットとしており、Amazon や他の書店で入手できます。
この本を購入することで、Lua プロジェクトのサポートにも役立てることができます。


12.1.1 – サイクルなしでのテーブルの保存

次の(より難しい)タスクはテーブルを保存することです。その方法には、テーブル構造に関する想定制約に応じた、いくつかの方法があります。1 つのアルゴリズムがすべてのケースに適しているわけではありません。簡単なテーブルでは、より簡単なアルゴリズムだけでなく、結果として生成されるファイルがより整然としたものになります。

最初の実装方法は次のとおりです。

    function serialize (o)
      if type(o) == "number" then
        io.write(o)
      elseif type(o) == "string" then
        io.write(string.format("%q", o))
      elseif type(o) == "table" then
        io.write("{\n")
        for k,v in pairs(o) do
          io.write("  ", k, " = ")
          serialize(v)
          io.write(",\n")
        end
        io.write("}\n")
      else
        error("cannot serialize a " .. type(o))
      end
    end
その関数はシンプルですが、それなりの仕事をこなします。テーブル構造がツリーであれば(つまり、サブテーブルの共有やサイクルがない場合)、入れ子のテーブル(つまり、他のテーブル内のテーブル)も処理します。小さな美的な改善点としては、入れ子のテーブルを適切にインデントすることです。練習として試してみることもできます。(ヒント:serialize にインデント文字列で余分なパラメーターを追加します。)

前の関数は、テーブル内のすべてのキーが有効な識別子であることを前提としています。テーブルに数値キーまたは構文的に有効な Lua 識別子でない文字列キーがある場合に、問題が発生します。この難点を解決するための簡単な方法は、次の行を変更することです。

          io.write("  ", k, " = ")
          io.write("  [")
          serialize(k)
          io.write("] = ")
に変更します。この変更により、美的には結果ファイルの改善にはなりませんが、関数のロバスト性が向上します。次の例を比較してください。
    -- result of serialize{a=12, b='Lua', key='another "one"'}
    -- first version
    {
      a = 12,
      b = "Lua",
      key = "another \"one\"",
    }
    
    -- second version
    {
      ["a"] = 12,
      ["b"] = "Lua",
      ["key"] = "another \"one\"",
    }
各ケースで角括弧が必要かどうかをテストすることで、この結果を改善できます。ここでも、この改善は練習として残しておきます。