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


3.6 – 表格建構函式

建構函式是建立並初始化表格的表達式。它們是 Lua 的一個顯著特徵,也是其最有用的多功能機制之一。

最簡單的建構函式是空建構函式 {},它建立一個空表格;我們之前見過它。建構函式還初始化陣列(也稱為序列清單)。例如,語句

    days = {"Sunday", "Monday", "Tuesday", "Wednesday",
            "Thursday", "Friday", "Saturday"}
將使用字串 "星期日" 初始化 days[1](第一個元素的索引始終為 1,而不是 0),使用 "星期一" 初始化 days[2],依此類推
    print(days[4])  --> Wednesday

建構函式不需要僅使用常量表達式。我們可以使用任何類型的表達式作為每個元素的值。例如,我們可以建立一個簡短的正弦表,如下所示

    tab = {sin(1), sin(2), sin(3), sin(4),
           sin(5), sin(6), sin(7), sin(8)}

若要初始化用作記錄的表格,Lua 提供以下語法

    a = {x=0, y=0}
這等於
    a = {}; a.x=0; a.y=0

無論我們使用哪個建構函式建立表格,我們始終可以向其中新增和移除任何類型的其他欄位

    w = {x=0, y=0, label="console"}
    x = {sin(0), sin(1), sin(2)}
    w[1] = "another field"
    x.f = w
    print(w["x"])   --> 0
    print(w[1])     --> another field
    print(x.f[1])   --> another field
    w.x = nil       -- remove field "x"
也就是說,所有表格都是平等建立的;建構函式僅影響其初始化。

每次 Lua 評估建構函式時,它都會建立並初始化一個新表格。因此,我們可以使用表格來實作連結清單

    list = nil
    for line in io.lines() do
      list = {next=list, value=line}
    end
此程式碼從標準輸入中讀取列並將它們儲存在連結清單中,以相反順序。清單中的每個節點都是一個具有兩個欄位的表格:value(包含列內容)和 next(包含對下一個節點的參考)。以下程式碼列印清單內容
    l = list
    while l do
      print(l.value)
      l = l.next
    end
(因為我們將清單實作為堆疊,所以列將以相反順序列印。)儘管具有指導意義,但我們幾乎不會在實際的 Lua 程式中使用上述實作;清單最好實作為陣列,正如我們將在 第 11 章 中看到的。

我們可以在同一個建構函式中混合記錄樣式和清單樣式初始化

    polyline = {color="blue", thickness=2, npoints=4,
                 {x=0,   y=0},
                 {x=-10, y=0},
                 {x=-10, y=1},
                 {x=0,   y=1}
               }
上述範例也說明了我們如何巢狀建構函式來表示更複雜的資料結構。每個元素polyline[1],...,polyline[4]都是表示記錄的表格
    print(polyline[2].x)    --> -10

這兩種建構函式形式有其限制。例如,您無法使用負索引或非適當識別碼的字串索引來初始化欄位。對於此類需求,還有另一種更通用的格式。在此格式中,我們明確地將要初始化的索引寫成方括號中的表達式

    opnames = {["+"] = "add", ["-"] = "sub",
               ["*"] = "mul", ["/"] = "div"}
    
    i = 20; s = "-"
    a = {[i+0] = s, [i+1] = s..s, [i+2] = s..s..s}
    
    print(opnames[s])    --> sub
    print(a[22])         --> ---
該語法較為繁瑣,但更靈活:清單樣式和記錄樣式都是這種更通用的特殊情況。建構函式
    {x=0, y=0}
等於
    {["x"]=0, ["y"]=0}
和建構函式
    {"red", "green", "blue"}
等於
    {[1]="red", [2]="green", [3]="blue"}

對於那些真的希望陣列從 0 開始的人來說,撰寫以下內容並不困難

    days = {[0]="Sunday", "Monday", "Tuesday", "Wednesday",
            "Thursday", "Friday", "Saturday"}
現在,第一個值 "星期日" 在索引 0。該零不影響其他欄位,但 "星期一" 自然會進入索引 1,因為它是建構函式中的第一個清單值;其他值隨後。儘管有此功能,我並不建議在 Lua 中使用從 0 開始的陣列。請記住,大多數函式都假設陣列從索引 1 開始,因此無法正確處理此類陣列。

您總可以在最後一個條目後加上逗號。這些尾隨逗號是可選的,但始終有效

    a = {[1]="red", [2]="green", [3]="blue",}
這種靈活性使得撰寫產生 Lua 表格的程式變得更容易,因為它們不需要將最後一個元素視為特殊情況。

最後,您總可以在建構函式中使用分號而不是逗號。我們通常保留分號來區分建構函式中的不同部分,例如將其清單部分與記錄部分分開

    {x=10, y=45; "one", "two", "three"}