この初版は Lua 5.0 向けに書かれました。後のバージョンでもほとんどは関連っていますが、多少の相違があります。
第 4 版は Lua 5.3 を対象としており、Amazon や他の書店で購入できます。
この本を購入することにより、Lua プロジェクトへの支援にも貢献できます。


12.1.2 – サイクルを含むテーブルの保存

一般的なトポロジー(つまり、サイクルや共有サブテーブルを含む)のテーブルを扱うには、別の方法が必要です。コンストラクタはこれらのテーブルを表すことができないため、ここでは使用しません。サイクルを表すには名前が必要なので、次の関数は保存される値とその名前を引数として受け取ります。さらに、サイクルが検出されたときに再利用できるように、すでに保存されたテーブルの名前を追跡しておく必要があります。この追跡にはもう 1 つのテーブルを使用します。このテーブルはテーブルをインデックスとして、対応する値として名前を持ちます。

保存するテーブルのキーは文字列または数値のみという制約を維持します。次の関数はこれらの基本タイプをシリアル化し、結果を返します

    function basicSerialize (o)
      if type(o) == "number" then
        return tostring(o)
      else   -- assume it is a string
        return string.format("%q", o)
      end
    end
次の関数が大変な作業を行います。saved パラメータはすでに保存されたテーブルを追跡するテーブルです
    function save (name, value, saved)
      saved = saved or {}       -- initial value
      io.write(name, " = ")
      if type(value) == "number" or type(value) == "string" then
        io.write(basicSerialize(value), "\n")
      elseif type(value) == "table" then
        if saved[value] then    -- value already saved?
          io.write(saved[value], "\n")  -- use its previous name
        else
          saved[value] = name   -- save name for next time
          io.write("{}\n")     -- create a new table
          for k,v in pairs(value) do      -- save its fields
            local fieldname = string.format("%s[%s]", name,
                                            basicSerialize(k))
            save(fieldname, v, saved)
          end
        end
      else
        error("cannot save a " .. type(value))
      end
    end
たとえば、次のようないテーブルを構築する場合
    a = {x=1, y=2; {3,4,5}}
    a[2] = a    -- cycle
    a.z = a[1]  -- shared sub-table
save('a', a) の呼び出しは次のように保存します。
    a = {}
    a[1] = {}
    a[1][1] = 3
    a[1][2] = 4
    a[1][3] = 5
    
    a[2] = a
    a["y"] = 2
    a["x"] = 1
    a["z"] = a[1]
(これらの代入の実際の順序は、テーブルの走査に依存するため異なる場合があります。それでも、このアルゴリズムにより、新しい定義に必要な以前のノードはすでに定義されていることが保証されます。)

共有部分を伴う複数の値を保存する場合は、同じ saved テーブルを使用して save を呼び出すことができます。たとえば、次の 2 つのテーブルを作成する場合

    a = {{"one", "two"}, 3}
    b = {k = a[1]}
次のように保存すると
    save('a', a)
    save('b', b)
結果は共通部分を持ちません
    a = {}
    a[1] = {}
    a[1][1] = "one"
    a[1][2] = "two"
    a[2] = 3
    b = {}
    b["k"] = {}
    b["k"][1] = "one"
    b["k"][2] = "two"
しかし、save の各呼び出しに同じ saved テーブルを使用すると
    local t = {}
    save('a', a, t)
    save('b', b, t)
結果は共通部分を共有します
    a = {}
    a[1] = {}
    a[1][1] = "one"
    a[1][2] = "two"
    a[2] = 3
    b = {}
    b["k"] = a[1]

Lua ではいつものことですが、他にもいくつかの選択肢があります。その中には、値にグローバル名を与えずに保存するもの(代わりに、チャンクでローカル値を作成してそれを返します)、関数(それぞれの関数をその名前に関連付けるテーブルを作成します)を扱うものなどがあります。Lua はその機能を提供します。仕組みは自分で構築します。