本第一版是為 Lua 5.0 所寫。儘管對後續版本而言仍然相當相關,但仍有一些差異。
第四版針對 Lua 5.3,可在 Amazon 和其他書店購買。
購買本書,您也可以協助 支援 Lua 專案


10.1 – 資料描述

Lua 網站保留了一個資料庫,其中包含使用 Lua 的全球專案範例。我們使用建構函式以自動記錄的方式呈現資料庫中的每個項目,如下列範例所示

    entry{
      title = "Tecgraf",
      org = "Computer Graphics Technology Group, PUC-Rio",
      url = "http://www.tecgraf.puc-rio.br/",
      contact = "Waldemar Celes",
      description = [[
        TeCGraf is the result of a partnership between PUC-Rio,
        the Pontifical Catholic University of Rio de Janeiro,
        and <A HREF="http://www.petrobras.com.br/">PETROBRAS</A>,
        the Brazilian Oil Company.
        TeCGraf is Lua's birthplace,
        and the language has been used there since 1993.
        Currently, more than thirty programmers in TeCGraf use
        Lua regularly; they have written more than two hundred
        thousand lines of code, distributed among dozens of
        final products.]]
      }
這種表示法的有趣之處在於,包含此類項目序列的檔案是一個 Lua 程式,它會呼叫函式 entry 的一系列呼叫,並使用表格作為呼叫引數。

我們的目標是撰寫一個程式,以 HTML 顯示該資料,以便它成為網頁 https://lua.dev.org.tw/uses.html。由於有許多專案,因此最終頁面會先顯示所有專案標題的清單,然後再顯示每個專案的詳細資訊。程式的結果如下所示

    <HTML>
    <HEAD><TITLE>Projects using Lua</TITLE></HEAD>
    <BODY BGCOLOR="#FFFFFF">
    Here are brief descriptions of some projects around the
    world that use <A HREF="home.html">Lua</A>.
    <BR>
    <UL>
    <LI><A HREF="#1">TeCGraf</A>
    <LI> ...
    </UL>
    
    <H3>
    <A NAME="1" HREF="http://www.tecgraf.puc-rio.br/">TeCGraf</A>
    <BR>
    <SMALL><EM>Computer Graphics Technology Group,
               PUC-Rio</EM></SMALL>
    </H3>
    
        TeCGraf is the result of a partnership between
        ...
        distributed among dozens of final products.<P>
    Contact: Waldemar Celes
    
    <A NAME="2"></A><HR>
    ...
    
    </BODY></HTML>

為了讀取資料,程式所要做的就是提供 entry 的適當定義,然後將資料檔案作為程式執行(使用 dofile)。請注意,我們必須兩次遍歷所有項目,第一次是為了標題清單,第二次是為了專案描述。第一種方法是將所有項目收集到一個陣列中。然而,由於 Lua 編譯得非常快,因此有一個有吸引力的第二種解決方案:兩次執行資料檔案,每次對 entry 使用不同的定義。我們在下一段程式中遵循此方法。

首先,我們定義一個用於撰寫格式化文字的輔助函式(我們已經在 第 5.2 節 中看過這個函式)

    function fwrite (fmt, ...)
      return io.write(string.format(fmt, unpack(arg)))
    end

BEGIN 函式僅撰寫頁面標題,它始終相同

    function BEGIN()
      io.write([[
        <HTML>
        <HEAD><TITLE>Projects using Lua</TITLE></HEAD>
        <BODY BGCOLOR="#FFFFFF">
        Here are brief descriptions of some projects around the
        world that use <A HREF="home.html">Lua</A>.
        <BR>
      ]])
    end

entry 的第一個定義將每個標題專案寫為清單項目。引數 o 將是描述專案的表格

    function entry0 (o)
      N=N + 1
      local title = o.title or '(no title)'
      fwrite('<LI><A HREF="#%d">%s</A>\n', N, title)
    end
如果 o.titlenil(即未提供欄位),函式會使用固定字串 "(no title)"

第二個定義會撰寫有關專案的所有有用資料。它稍微複雜一些,因為所有項目都是選用的。

    function entry1 (o)
      N=N + 1
      local title = o.title or o.org or 'org'
      fwrite('<HR>\n<H3>\n')
      local href = ''
    
      if o.url then
        href = string.format(' HREF="%s"', o.url)
      end
      fwrite('<A NAME="%d"%s>%s</A>\n', N, href, title)
    
      if o.title and o.org then
        fwrite('<BR>\n<SMALL><EM>%s</EM></SMALL>', o.org)
      end
      fwrite('\n</H3>\n')
    
      if o.description then
        fwrite('%s', string.gsub(o.description,
                                 '\n\n\n*', '<P>\n'))
        fwrite('<P>\n')
      end
    
      if o.email then
        fwrite('Contact: <A HREF="mailto:%s">%s</A>\n',
               o.email, o.contact or o.email)
      elseif o.contact then
        fwrite('Contact: %s\n', o.contact)
      end
    end
(為了避免與使用雙引號的 HTML 衝突,我們在此程式中僅使用單引號。)最後一個函式會關閉頁面
    function END()
      fwrite('</BODY></HTML>\n')
    end
最後,主程式開始頁面,執行資料檔案與第一個 entry 定義 (entry0) 來建立標題清單,然後再次執行資料檔案與第二個 entry 定義,並關閉頁面
    BEGIN()
    
    N = 0
    entry = entry0
    fwrite('<UL>\n')
    dofile('db.lua')
    fwrite('</UL>\n')
    
    N = 0
    entry = entry1
    dofile('db.lua')
    
    END()