此初版是為 Lua 5.0 所寫。儘管在後續版本中仍有很大關聯性,但仍有一些差異。
第四版針對 Lua 5.3,可在 Amazon 和其他書店購買。
購買此書,您也能協助 支援 Lua 專案


17.3 – 重新檢視具有預設值的表格

第 13.4.3 節 中,我們討論如何實作具有非 nil 預設值的表格。我們看過一種特定技術,並評論說其他兩種技術需要弱表格,因此我們將其延後。現在是重新檢視此主題的時候了。正如我們將看到的,這兩種預設值技術實際上是我們在此處所見兩種一般技術的特定應用:物件屬性和記憶化。

在第一個解法中,我們使用弱表格將預設值關聯到每個表格

    local defaults = {}
    setmetatable(defaults, {__mode = "k"})
    local mt = {__index = function (t) return defaults[t] end}
    function setDefault (t, d)
      defaults[t] = d
      setmetatable(t, mt)
    end
如果 defaults 沒有弱鍵,它會將所有具有預設值的表格錨定到永久存在。

在第二個解法中,我們為不同的預設值使用不同的元表格,但每當我們重複預設值時,我們會重複使用相同的元表格。這是一個典型的記憶化用途

    local metas = {}
    setmetatable(metas, {__mode = "v"})
    function setDefault (t, d)
      local mt = metas[d]
      if mt == nil then
        mt = {__index = function () return d end}
        metas[d] = mt     -- memoize
      end
      setmetatable(t, mt)
    end
在這種情況下,我們使用弱值來允許收集不再使用的元表格。

針對預設值的這兩個實作,哪一個最好?和往常一樣,這取決於情況。兩者具有類似的複雜度和類似效能。第一個實作需要幾個字元來表示具有預設值的每個表格(defaults 中的一個條目)。第二個實作需要幾個十個字元來表示每個不同的預設值(一個新表格、一個新封閉,以及 metas 中的一個條目)。因此,如果您的應用程式有數千個具有幾個不同預設值的表格,則第二個實作明顯優於第一個實作。另一方面,如果少數表格共用共同預設值,則您應該使用第一個實作。