第一版是為 Lua 5.0 編寫的。儘管在很大程度上仍然適用於後續版本,但有一些不同。
第四版針對 Lua 5.3,可在 Amazon 和其他書店購買。
購買本書,您還可以幫助 支持 Lua 項目


17.1 – 記憶化函數

一種常見的編程技術是用空間換取時間。您可以通過記憶化函數結果來加速某些函數,以便以後使用相同參數呼叫函數時,它可以重複使用結果。

想像一個通用伺服器,它接收包含 Lua 程式碼字串的請求。每次收到請求時,它都會對字串執行 loadstring,然後呼叫結果函數。但是,loadstring 是一個昂貴的函數,而對伺服器的某些命令可能非常頻繁。伺服器可以記憶化 loadstring 的結果,使用輔助表,而不是在每次收到 "closeconnection()" 之類的通用命令時重複呼叫 loadstring。在呼叫 loadstring 之前,伺服器會在表中檢查該字串是否已經有轉換。如果找不到字串,則(且僅當)伺服器呼叫 loadstring 並將結果儲存在表中。我們可以將此行為封裝到一個新函數中

    local results = {}
    function mem_loadstring (s)
      if results[s] then      -- result available?
        return results[s]     -- reuse it
      else
        local res = loadstring(s)   -- compute new result
        results[s] = res            -- save for later reuse
        return res
      end
    end

此方案可以節省大量的空間。不過,它也可能造成意想不到的浪費。雖然有些命令會重複執行,但許多其他命令只會執行一次。隨著時間的推移,表格 results 會累積伺服器曾經接收過的所有命令及其各自的代碼;經過一段時間後,這將耗盡伺服器的記憶體。一個弱表格提供了一個簡單的解決方案來解決此問題。如果 results 表格具有弱值,每個垃圾回收週期都會移除在當時未使用的所有轉譯(這表示幾乎所有轉譯都會被移除)

    local results = {}
    setmetatable(results, {__mode = "v"})  -- make values weak
    function mem_loadstring (s)
       ...    -- as before
實際上,由於索引始終為字串,如果需要,我們可以讓該表格完全變弱
    setmetatable(results, {__mode = "kv"})
最終結果完全相同。

memoize 技術也可以用來確保某種物件的唯一性。例如,假設一個系統將顏色表示為表格,其中包含某些範圍內的欄位 redgreenblue。一個天真的顏色工廠會為每個新要求產生一個新顏色

    function createRGB (r, g, b)
      return {red = r, green = g, blue = b}
    end
使用 memoize 技術,我們可以為相同的顏色重複使用相同的表格。若要為每個顏色建立一個唯一的金鑰,我們只需將顏色索引與中間的分隔符號串接起來
    local results = {}
    setmetatable(results, {__mode = "v"})  -- make values weak
    function createRGB (r, g, b)
      local key = r .. "-" .. g .. "-" .. b
      if results[key] then return results[key]
      else
        local newcolor = {red = r, green = g, blue = b}
        results[key] = newcolor
        return newcolor
      end
    end
此實作的一個有趣結果是,使用者可以使用原始相等運算子來比較顏色,因為兩個共存的相等顏色總是會由相同的表格表示。請注意,相同的顏色可能會在不同的時間由不同的表格表示,因為垃圾回收器週期會不時清除 results 表格。不過,只要給定的顏色正在使用中,它就不會從 results 中移除。因此,只要一個顏色存活的時間夠長,可以與新的顏色進行比較,其表示也會存活的時間夠長,可以被新的顏色重複使用。