Luaref

Nvim :help 頁面,從 原始碼 使用 tree-sitter-vimdoc 解析器 生成


LUA 參考手冊
版本 0.3.0,2022 年 8 月 7 日
Vimdoc 版本 (c) 2006 Luis Carvalho <lexcarvalho at gmail dot com>
改編自 "Lua: 5.1 參考手冊",R. Ierusalimschy, L. H. de Figueiredo, W. Celes 版權 (c) 2006 Lua.org, PUC-Rio。
有關本手冊的資訊,請參閱 lua-ref-doc。有關版權和許可證,請參閱 lua-ref-copyright

1 簡介 luaref-intro

Lua 是一種擴展程式語言,旨在支援一般程序式程式設計和資料描述功能。它也為物件導向程式設計、函數式程式設計和資料驅動程式設計提供良好的支援。Lua 的目標是作為一個強大、輕量級的腳本語言,用於任何需要腳本語言的程式。Lua 以函式庫的形式實現,用清晰的 C 語言(即 ANSI C 和 C++ 的通用子集)編寫。
作為一種擴展語言,Lua 沒有「主」程式的概念:它僅在一個稱為嵌入程式或簡稱主機的客戶端中嵌入工作。這個主機程式可以呼叫函數來執行一段 Lua 程式碼、可以讀寫 Lua 變數,並可以註冊 C 函數以供 Lua 程式碼呼叫。透過使用 C 函數,Lua 可以擴充以應對各種不同的領域,從而建立共享語法框架的客製化程式語言。
Lua 是自由軟體,並且如往常一樣,在許可證中聲明不提供任何保證。本手冊中描述的實現在 Lua 的官方網站 www.lua.org 上提供。
與任何其他參考手冊一樣,本文件在某些地方會比較枯燥。有關 Lua 設計背後決策的討論,請參閱 lua-ref-bibliography 中的參考資料。有關 Lua 程式設計的詳細介紹,請參閱 Roberto 的書籍,《Programming in Lua》。
Lua 在葡萄牙語中意為「月亮」,發音為 LOO-ah。

2 語言 lua-language

本節描述 Lua 的詞彙、語法和語意。換句話說,本節描述哪些符號是有效的,它們如何組合,以及它們的組合意義是什麼。
將使用通常的擴展 BNF 表示法來解釋語言構造,其中 { a } 表示 0 個或多個 a,而 [ a ] 表示可選的 a

2.1 詞法約定 lua-lexical

lua-names lua-identifiers Lua 中的名稱(也稱為識別符號)可以是任何由字母、數字和底線組成的字串,但不能以數字開頭。這與大多數語言中識別符號的定義一致。(字母的定義取決於當前的語言環境:當前語言環境認為是字母的任何字元都可以在識別符號中使用。)識別符號用於命名變數和表格欄位。
以下關鍵字是保留字,不能用作名稱
and       break     do        else      elseif
end       false     for       function  if
in        local     nil       not       or
repeat    return    then      true      until     while
Lua 是一種區分大小寫的語言:and 是一個保留字,但 AndAND 是兩個不同的有效名稱。按照慣例,以底線開頭,後跟大寫字母(例如 _VERSION)的名稱是為 Lua 使用的內部全域變數保留的。
以下字串表示其他符號
+     -     *     /     %     ^     #
==    ~=    <=    >=    <     >     =
(     )     {     }     [     ]
;     :     ,     .     ..    ...
lua-literal
字串字面值可以用單引號或雙引號括起來,並且可以包含以下類似 C 的跳脫序列
\a 響鈴
\b 退格
\f 換頁
\n 換行
\r 返回
\t 水平制表符
\v 垂直制表符
\\ 反斜線
\" 引號(雙引號)
\' 單引號(單引號)
此外,反斜線後跟一個實際換行符會導致字串中出現換行符。字串中的字元也可以使用跳脫序列 \ddd 指定其數值,其中 ddd 是一個最多三位十進位數字的序列。(請注意,如果要使數字跳脫符號後跟數字,則必須使用正好三位數字表示。)Lua 中的字串可以包含任何 8 位值,包括嵌入的零,可以指定為 \0
若要將雙引號(單引號)、換行符、反斜線或嵌入的零放入用雙引號(單引號)括起來的字面值字串中,必須使用跳脫序列。任何其他字元都可以直接插入字面值中。(某些控制字元可能會導致檔案系統出現問題,但 Lua 沒有問題。)
字面值字串也可以使用長括號括起來的長格式定義。我們將 n 級的開長括號定義為一個開方括號,後跟 n 個等號,後跟另一個開方括號。因此,0 級的開長括號寫為 [[,1 級的開長括號寫為 [=[,依此類推。類似地定義閉長括號;例如,4 級的閉長括號寫為 ]====]。長字串以任何級別的開長括號開始,並在第一個相同級別的閉長括號處結束。此括號形式中的字面值可以跨越多行,不解釋任何跳脫序列,並且忽略任何其他級別的長括號。它們可以包含任何內容,除了正確級別的閉括號。
為了方便起見,當開長括號後面緊跟換行符時,換行符不包含在字串中。例如,在使用 ASCII 的系統中(其中 a 編碼為 97,換行符編碼為 10,1 編碼為 49),以下五個字面值表示相同的字串
a = 'alo\n123"'
a = "alo\n123\""
a = '\97lo\10\04923"'
a = [[alo
123"]]
a = [==[
alo
123"]==]
lua-numconstant
數值常數可以寫成帶有可選小數部分和可選小數指數的形式。Lua 也接受整數十六進位常數,方法是在其前面加上 0x。有效數值常數的範例為
3     3.0     3.1416  314.16e-2   0.31416E1   0xff   0x56
lua-comment
註解以雙連字符 (--) 開頭,位於字串外的任何位置。如果 -- 後面的文字不是開長括號,則註解是短註解,將執行到行尾。否則,它是長註解,將執行到對應的閉長括號。長註解經常被用來暫時停用程式碼。

2.2 值和類型 lua-values

Lua 是一種動態類型語言。這意味著變數沒有類型;只有值才有類型。該語言中沒有類型定義。所有值都有自己的類型。
Lua 中的所有值都是一級值。這表示所有值都可以儲存在變數中、作為引數傳遞給其他函式以及作為結果回傳。
lua-types lua-nil lua-true lua-false lua-number lua-string Lua 中有八種基本類型:nilbooleannumberstringfunctionuserdatathreadtable。Nil 是值 nil 的類型,其主要特性是與任何其他值不同;它通常表示缺少有用的值。Boolean 是值 falsetrue 的類型。nilfalse 都會使條件為 false;任何其他值都會使條件為 true。Number 表示實數(雙精度浮點數)。(很容易建立使用其他內部表示數值(例如單精度浮點數或長整數)的 Lua 直譯器;請參閱檔案 luaconf.h。)String 表示字元陣列。Lua 是 8 位元清除的:字串可以包含任何 8 位元字元,包括嵌入的零 (\0)(請參閱 lua-literal)。
Lua 可以呼叫(和操作)用 Lua 編寫的函式和用 C 編寫的函式(請參閱 lua-function)。
lua-userdatatype
提供 userdata 類型,以允許將任意 C 資料儲存在 Lua 變數中。此類型對應於原始記憶體區塊,並且在 Lua 中沒有預先定義的操作,但賦值和身分測試除外。但是,透過使用元表格,程式設計師可以為 userdata 值定義操作(請參閱 lua-metatable)。UserData 值無法在 Lua 中建立或修改,只能透過 C API。這保證了主機程式擁有的資料的完整性。
lua-thread
thread 類型表示獨立的執行緒,用於實作協同程式(請參閱 lua-coroutine)。請勿將 Lua 執行緒與作業系統執行緒混淆。Lua 在所有系統上都支援協同程式,即使是那些不支援執行緒的系統。
lua-table
table 類型實作關聯陣列,也就是說,可以使用數字以及任何值(nil 除外)作為索引的陣列。表格可以是異質的;也就是說,它們可以包含所有類型的值(nil 除外)。表格是 Lua 中唯一資料結構機制;它們可以用來表示普通陣列、符號表、集合、記錄、圖形、樹狀結構等。為了表示記錄,Lua 使用欄位名稱作為索引。該語言透過提供 a.name 作為 a["name"] 的語法糖來支援這種表示。在 Lua 中建立表格有多種方便的方法(請參閱 lua-tableconstructor)。
與索引一樣,表格欄位的值可以是任何類型(nil 除外)。特別是,由於函式是一級值,因此表格欄位可能包含函式。因此,表格也可以攜帶方法(請參閱 lua-function-define)。
表格、函式、執行緒和(完整)userdata 值都是物件:變數實際上不包含這些值,只包含對它們的參考。賦值、參數傳遞和函式回傳始終會操作對這些值的參考;這些操作不暗示任何類型的複製。
函式庫的 type 函式會回傳一個字串,描述給定值的類型(請參閱 lua-type())。

2.2.1 強制轉型 lua-coercion

Lua 在執行時期提供字串和數值之間的自動轉換。任何應用於字串的算術運算都會嘗試將該字串轉換為數值,並遵循通常的轉換規則。反之,當預期是字串時使用數值,該數值會以合理的格式轉換為字串。若要完全控制數值如何轉換為字串,請使用字串函式庫中的 format 函式(請參閱 string.format())。

2.3 變數 lua-variables

變數是儲存值的地方。Lua 中有三種變數:全域變數、區域變數和表格欄位。
單一名稱可以表示全域變數或區域變數(或函式的形式參數,這是一種特殊的區域變數形式)。
var ::= Name
名稱表示識別符,如 lua-lexical 中所定義。
除非明確宣告為區域變數(請參閱 lua-local),否則任何變數都假定為全域變數。區域變數具有詞法作用域:在它們的作用域內定義的函式可以自由存取區域變數(請參閱 lua-visibility)。
在首次賦值給變數之前,其值為 nil
方括號用於索引表格。
var ::= prefixexp [ exp ]
第一個表達式(prefixexp)應產生一個表格值;第二個表達式(exp)識別該表格內的一個特定條目。表示要索引的表格的表達式具有受限的語法;請參閱 lua-expressions 以了解詳細資訊。
語法 var.NAME 只是 var["NAME"] 的語法糖。
var ::= prefixexp . Name
所有全域變數都作為一般 Lua 表格中的欄位存在,稱為環境表格或簡稱環境(請參閱 lua-environments)。每個函式都有其自己的環境參考,因此該函式中的所有全域變數都將參考此環境表格。建立函式時,它會從建立它的函式繼承環境。若要取得 Lua 函式的環境表格,請呼叫 getfenv(請參閱 lua_getfenv())。若要取代它,請呼叫 setfenv(請參閱 setfenv())。 (您只能透過除錯函式庫來操作 C 函式的環境;請參閱 lua-lib-debug。)
存取全域變數 x 等同於 _env.x,而這又等同於
gettable_event(_env, "x")
其中 _env 是執行函式的環境。(_env 變數未在 Lua 中定義。我們在這裡使用它僅用於說明目的。)
對全域變數和表格欄位的存取意義可以透過元表格來變更。存取索引變數 t[i] 等同於呼叫 gettable_event(t,i)。(請參閱 lua-metatable 以了解 gettable_event 函式的完整說明。此函式未在 Lua 中定義或可呼叫。我們在這裡使用它僅用於說明目的。)

2.4 陳述式 lua-statement

Lua 支援一組幾乎傳統的陳述式,類似於 Pascal 或 C 中的陳述式。這組陳述式包括賦值、控制結構、函式呼叫和變數宣告。

2.4.1 程式碼塊 lua-chunk

Lua 的執行單位稱為程式碼塊。程式碼塊只是一個陳述式序列,這些陳述式會依序執行。每個陳述式後面都可以選擇性地跟隨分號。
chunk ::= {stat [ ; ]}
沒有空的陳述式,因此 ;; 不是合法的。
Lua 將程式碼塊視為具有可變數量參數的匿名函式主體(請參閱 lua-function-define)。因此,程式碼塊可以定義區域變數、接收參數和回傳值。
程式碼塊可以儲存在檔案中或主機程式內的字串中。執行程式碼塊時,首先會將其預先編譯為虛擬機的指令,然後由虛擬機的解譯器執行已編譯的程式碼。
程式碼塊也可以預先編譯為二進位形式;請參閱程式 luac 以了解詳細資訊。來源和已編譯形式的程式可以互換;Lua 會自動偵測檔案類型並採取相應的動作。

2.4.2 區塊 lua-block

區塊是陳述式的清單;在語法上,區塊與程式碼塊相同。
block ::= chunk
lua-do lua-end 可以明確分隔區塊,以產生單一陳述式。
stat ::= do block end
明確的區塊對於控制變數宣告的作用域很有用。明確的區塊有時也用於在另一個區塊的中間新增 returnbreak 陳述式(請參閱 lua-control)。

2.4.3 賦值 lua-assign

Lua 允許多重賦值。因此,賦值的語法在左側定義變數清單,在右側定義表達式清單。兩個清單中的元素都用逗號分隔。
stat ::= varlist1 = explist1
varlist1 ::= var { , var }
explist1 ::= exp { , exp }
表達式在 lua-expressions 中討論。
在賦值之前,會將值的清單調整為變數清單的長度。如果值的數量超出需要,則會捨棄多餘的值。如果值的數量少於需要,則會使用所需數量的 nil 擴充清單。如果表達式清單以函式呼叫結尾,則此呼叫所回傳的所有值都會在調整之前進入值的清單中(除非呼叫包含在括號中;請參閱 lua-expressions)。
賦值陳述式首先會評估其所有表達式,然後才會執行賦值。因此,程式碼
i = 3
i, a[i] = i+1, 20
會將 a[3] 設定為 20,而不會影響 a[4],因為 a[i] 中的 i 會在賦值為 4 之前評估(為 3)。同樣地,這一行
x, y = y, x
會交換 xy 的值。
對全域變數和表格欄位的賦值意義可以透過元表格來變更。賦值給索引變數 t[i] = val 等同於 settable_event(t,i,val)。(請參閱 lua-metatable 以了解 settable_event 函式的完整說明。此函式未在 Lua 中定義或可呼叫。我們在這裡使用它僅用於說明目的。)
賦值給全域變數 x = val 等同於賦值 _env.x = val,而這又等同於
settable_event(_env, "x", val)
其中 _env 是執行函式的環境。(_env 變數未在 Lua 中定義。我們在這裡使用它僅用於說明目的。)

2.4.4 控制結構 lua-control

lua-if lua-then lua-else lua-elseif lua-while lua-repeat lua-until 控制結構 ifwhilerepeat 具有通常的意義和熟悉的語法。
stat ::=  while  exp do block end
stat ::=  repeat  block until exp
stat ::=  if  exp then block { elseif exp then block }
          [ else block ] end
Lua 還有一個 for 陳述式,有兩種形式(請參閱 lua-for)。
控制結構的條件表達式可以回傳任何值。falsenil 都被視為 false。所有與 nilfalse 不同的值都被視為 true(特別是,數字 0 和空字串也被視為 true)。
repeat-until 迴圈中,內部區塊不會在 until 關鍵字處結束,而是在條件之後才結束。因此,條件可以參考在迴圈區塊內宣告的區域變數。
lua-return
return 陳述式用於從函式或程式碼塊(僅是一個函式)回傳值。函式和程式碼塊可以回傳多個值,因此 return 陳述式的語法為
stat ::= return [explist1]
lua-break
break 陳述式用於終止 whilerepeatfor 迴圈的執行,跳到迴圈後的下一個陳述式。
stat ::= break
break 會結束最內層的封閉迴圈。
returnbreak 陳述式只能寫為區塊的last 陳述式。如果確實需要在區塊中間 returnbreak,則可以使用明確的內部區塊,例如慣用語 do return enddo break end,因為現在 returnbreak 是它們的(內部)區塊中的最後一個陳述式。

2.4.5 For 陳述式 for lua-for

for 陳述式有兩種形式:一種是數值形式,一種是通用形式。
數值 for 迴圈會重複執行程式碼區塊,同時控制變數會執行算術級數。它具有以下語法
stat ::=  for  Name = exp , exp [ , exp ] do block end
block 會重複執行,name 從第一個 exp 的值開始,直到它以第三個 exp 的步進值通過第二個 exp。更精確地說,類似於以下的 for 陳述式
for var = e1, e2, e3 do block end
等同於程式碼
do
  local  var, limit, step  = tonumber(e1), tonumber(e2), tonumber(e3)
  if not (  var  and  limit  and  step  ) then error() end
  while (  step  >0 and  var  <=  limit  )
          or (  step  <=0 and  var  >=  limit  ) do
     block
     var  =  var  +  step
  end
end
請注意以下事項
所有三個控制表達式只會評估一次,在迴圈開始之前。它們都必須產生數值。
varlimitstep 是不可見的變數。這裡的名稱僅用於說明目的。
如果沒有第三個表達式(步進值),則會使用步進值 1。
您可以使用 break 來結束 for 迴圈。
迴圈變數 var 是迴圈的區域變數;您無法在 for 結束或中斷後使用其值。如果您需要此值,請在結束或中斷迴圈之前將其賦值給另一個變數。
for-in
通用 for 陳述式會處理稱為 iterator 的函式。在每次迭代時,都會呼叫 iterator 函式來產生新值,並在新值為 nil 時停止。通用 for 迴圈具有以下語法
stat ::=  for  namelist in explist1 do block end
namelist ::= Name { , Name }
類似於以下的 for 陳述式
for var1, ..., varn in explist do block end
等同於程式碼
do
  local  f, s, var  =  explist
  while true do
      local  var1, ..., varn  =  f(s, var)
      var  =  var1
      if  var  == nil then break end
      block
  end
end
請注意以下事項
只會評估一次 explist。其結果是一個 iterator 函式、一個 state 以及第一個 iterator 變數的初始值。
fsvar 是不可見的變數。這裡的名稱僅用於說明目的。
您可以使用 break 來結束 for 迴圈。
迴圈變數 var1, ..., varn 是迴圈的區域變數;您無法在 for 結束後使用其值。如果您需要這些值,請在結束或中斷迴圈之前將其賦值給其他變數。

2.4.6 函式呼叫作為陳述式 lua-funcstatement

為了允許可能的副作用,函式呼叫可以作為陳述式執行。
stat ::= functioncall
在這種情況下,所有回傳的值都會被捨棄。函式呼叫在 lua-function 中說明。

2.4.7 區域宣告 lua-local

區域變數可以宣告在區塊內的任何位置。宣告可以包括初始賦值。
stat ::=  local  namelist [ = explist1 ]
namelist ::= Name { , Name }
如果存在,初始賦值具有與多重賦值相同的語意(請參閱 lua-assign)。否則,所有變數都會使用 nil 初始化。
程式碼塊也是一個區塊(請參閱 lua-chunk),因此可以在任何明確區塊之外的程式碼塊中宣告區域變數。此類區域變數的作用域會延伸到程式碼塊的結尾。
區域變數的可见性規則在 lua-visibility 中說明。

2.5 表達式 lua-expressions

Lua 中的基本表達式如下:
exp ::= prefixexp
exp ::=  nil  |  false  |  true
exp ::= Number
exp ::= String
exp ::= function
exp ::= tableconstructor
exp ::= ...
exp ::= exp binop exp
exp ::= unop exp
prefixexp ::= var | functioncall | ( exp )
數字和字串常值在 lua-lexical 中說明;變數在 lua-variables 中說明;函式定義在 lua-function-define 中說明;函式呼叫在 lua-function 中說明;表格建構式在 lua-tableconstructor 中說明。可變參數表達式,以三個點 (...) 表示,只能在可變參數函式內部使用;它們在 lua-function-define 中說明。
二元運算子包含算術運算子 (請參閱 lua-arithmetic)、關係運算子 (請參閱 lua-relational)、邏輯運算子 (請參閱 lua-logicalop) 和串聯運算子 (請參閱 lua-concat)。一元運算子包含一元負號 (請參閱 lua-arithmetic)、一元 not (請參閱 lua-logicalop) 和一元長度運算子 (請參閱 lua-length)。
函式呼叫和可變參數表達式都可能產生多個值。如果表達式被用作陳述句 (請參閱 lua-funcstatement) (僅適用於函式呼叫),則其回傳列表會調整為零個元素,從而捨棄所有回傳值。如果表達式被用作表達式列表的最後一個 (或唯一) 元素,則不會進行調整 (除非呼叫被括在括號中)。在所有其他情況下,Lua 會將結果列表調整為一個元素,捨棄除第一個值之外的所有值。
以下是一些範例
f()                -- adjusted to 0 results
g(f(), x)          -- f() is adjusted to 1 result
g(x, f())          -- g gets x plus all results from f()
a,b,c = f(), x     -- f() is adjusted to 1 result (c gets nil)
a,b = ...          -- a gets the first vararg parameter, b gets
                   -- the second (both a and b may get nil if there
                   -- is no corresponding vararg parameter)
a,b,c = x, f()     -- f() is adjusted to 2 results
a,b,c = f()        -- f() is adjusted to 3 results
return f()         -- returns all results from f()
return ...         -- returns all received vararg parameters
return x,y,f()     -- returns x, y, and all results from f()
{f()}              -- creates a list with all results from f()
{...}              -- creates a list with all vararg parameters
{f(), nil}         -- f() is adjusted to 1 result
括在括號中的表達式總是只產生一個值。因此,(f(x,y,z)) 永遠是一個單一值,即使 f 回傳多個值也是如此。((f(x,y,z)) 的值是 f 回傳的第一個值,如果 f 沒有回傳任何值,則為 nil。)

2.5.1 算術運算子 lua-arithmetic

Lua 支援常用的算術運算子:二元 + (加法)、- (減法)、* (乘法)、/ (除法)、% (模數) 和 ^ (指數);以及一元 - (負號)。如果運算元是數字,或可以轉換為數字的字串 (請參閱 lua-coercion),則所有運算都具有通常的含義。指數運算適用於任何指數。例如,x^(-0.5) 計算 x 平方根的倒數。模數定義為
a % b == a - math.floor(a/b)*b
也就是說,它是將商朝負無窮大方向取整的除法餘數。

2.5.2 關係運算子 lua-relational

Lua 中的關係運算子為
==    ~=    <     >     <=    >=
這些運算子總是產生 falsetrue
相等 (==) 首先比較運算元的類型。如果類型不同,則結果為 false。否則,將比較運算元的值。數字和字串以通常的方式進行比較。物件 (表格、userdata、執行緒和函式) 按參考進行比較:只有當兩個物件是同一個物件時,才認為它們相等。每次您建立一個新的物件 (表格、userdata 或函式) 時,這個新的物件都與任何先前存在的物件不同。
您可以使用 "eq" 元方法 (請參閱 lua-metatable) 來變更 Lua 比較表格和 userdata 的方式。
強制轉換的轉換規則 lua-coercion 不適用於相等比較。因此,"0"==0 的計算結果為 false,而 t[0]t["0"] 表示表格中的不同條目。
運算子 ~= 正好是相等 (==) 的否定。
順序運算子的運作方式如下。如果兩個參數都是數字,則它們會像數字一樣進行比較。否則,如果兩個參數都是字串,則會根據目前的語言環境比較它們的值。否則,Lua 會嘗試呼叫 "lt" 或 "le" 元方法 (請參閱 lua-metatable)。

2.5.3 邏輯運算子 lua-logicalop

Lua 中的邏輯運算子為
and    or    not
與控制結構 (請參閱 lua-control) 一樣,所有邏輯運算子都將 falsenil 視為 false,而將其他任何內容視為 true。
lua-not lua-and lua-or 否定運算子 not 總是回傳 falsetrue。連詞運算子 and 如果第一個參數的值為 falsenil,則回傳第一個參數;否則,and 會回傳第二個參數。析取運算子 or 如果第一個參數的值與 nilfalse 不同,則回傳第一個參數;否則,or 會回傳第二個參數。andor 都使用短路求值,也就是說,只有在必要時才會評估第二個運算元。以下是一些範例
10 or 20            --> 10
10 or error()       --> 10
nil or "a"          --> "a"
nil and 10          --> nil
false and error()   --> false
false and nil       --> false
false or nil        --> nil
10 and 20           --> 20
(在本手冊中,--> 表示前一個表達式的結果。)

2.5.4 串聯 lua-concat

Lua 中的字串串聯運算子用兩個點 (..) 表示。如果兩個運算元都是字串或數字,則會根據 lua-coercion 中提及的規則將它們轉換為字串。否則,會呼叫 "concat" 元方法 (請參閱 lua-metatable)。

2.5.5 長度運算子 lua-# lua-length

長度運算子用一元運算子 # 表示。字串的長度是其位元組數 (也就是說,當每個字元都是一個位元組時,字串長度的通常含義)。
表格 t 的長度定義為任何整數索引 n,使得 t[n] 不是 nilt[n+1]nil;此外,如果 t[1]nil,則 n 可以為零。對於一個常規陣列,其中從 1 到給定的 n 的值都不是 nil,其長度正好是該 n,即其最後一個值的索引。如果陣列有「空洞」(也就是說,在其他非 nil 值之間存在 nil 值),則 #t 可以是直接位於 nil 值之前的任何索引 (也就是說,它可以將任何此類 nil 值視為陣列的結尾)。

2.5.6 優先順序 lua-precedence

Lua 中的運算子優先順序遵循下表,從低到高優先順序
or
and
<     >     <=    >=    ~=    ==
..
+     -
*     /
not   #     - (unary)
^
如同通常情況一樣,您可以使用括號來變更表達式中的優先順序。串聯 (..) 和指數 (^) 運算子是右結合的。所有其他二元運算子都是左結合的。

2.5.7 表格建構式 lua-tableconstructor

表格建構式是建立表格的表達式。每次評估建構式時,都會建立一個新的表格。建構式可用於建立空表格,或建立表格並初始化其某些欄位。建構式的一般語法為
tableconstructor ::= { [ fieldlist ] }
fieldlist ::= field { fieldsep field } [ fieldsep ]
field ::= [ exp ]  = exp | Name = exp | exp
fieldsep ::=  , |  ;
每個形式為 [exp1] = exp2 的欄位都會將一個鍵為 exp1、值為 exp2 的條目新增到新表格中。形式為 name = exp 的欄位等效於 ["name"] = exp。最後,形式為 exp 的欄位等效於 [i] = exp,其中 i 是從 1 開始的連續數字整數。其他格式的欄位不會影響此計數。例如,
a = { [f(1)] = g; "x", "y"; x = 1, f(x), [30] = 23; 45 }
等效於
do
  local t = {}
  t[f(1)] = g
  t[1] = "x"         -- 1st exp
  t[2] = "y"         -- 2nd exp
  t.x = 1            -- temp["x"] = 1
  t[3] = f(x)        -- 3rd exp
  t[30] = 23
  t[4] = 45          -- 4th exp
  a = t
end
如果列表中的最後一個欄位具有 exp 的形式,且該表達式是函式呼叫,則呼叫回傳的所有值都會連續輸入列表 (請參閱 lua-function)。為了避免這種情況,請將函式呼叫括在括號中 (請參閱 lua-expressions)。
欄位列表可以有一個可選的尾隨分隔符,以便於機器產生的程式碼。

2.5.8 函式呼叫 lua-function

Lua 中的函式呼叫具有以下語法
functioncall ::= prefixexp args
在函式呼叫中,首先評估 prefixexpargs。如果 prefixexp 的值具有 function 類型,則會使用給定的引數呼叫此函式。否則,會呼叫 prefixexp 「呼叫」元方法,其第一個參數為 prefixexp 的值,後接原始呼叫引數 (請參閱 lua-metatable)。
形式
functioncall ::= prefixexp : Name args
可用於呼叫「方法」。呼叫 v:name( args )v.name(v, args ) 的語法糖,但 v 只會評估一次。
引數具有以下語法
args ::=  ( [ explist1 ] )
args ::= tableconstructor
args ::= String
所有引數表達式都會在呼叫之前評估。形式為 f{ fields } 的呼叫是 f({ fields }) 的語法糖,也就是說,引數列表是一個新的單一表格。形式為 f' string ' (或 f" string "f[[ string ]]) 的呼叫是 f(' string ') 的語法糖,也就是說,引數列表是一個單一字串常值。
作為 Lua 自由格式語法的例外,您不能在函式呼叫中的 ( 之前放置換行符號。此限制避免了語言中的一些歧義。如果您寫
a = f
(g).x(a)
Lua 會將其視為單一陳述句,a = f(g).x(a)。因此,如果您想要兩個陳述句,則必須在它們之間新增分號。如果您真的想要呼叫 f,則必須移除 (g) 之前的換行符號。
lua-tailcall
形式為 return functioncall 的呼叫稱為尾呼叫。Lua 實作了正確的尾呼叫 (或正確的尾遞迴):在尾呼叫中,被呼叫的函式會重複使用呼叫函式的堆疊項目。因此,程式可以執行的巢狀尾呼叫數量沒有限制。但是,尾呼叫會清除有關呼叫函式的任何偵錯資訊。請注意,尾呼叫只會發生在特定語法中,其中 return 只有一個函式呼叫作為引數;此語法會讓呼叫函式完全回傳被呼叫函式的回傳值。因此,以下範例都不是尾呼叫
return (f(x))        -- results adjusted to 1
return 2 * f(x)
return x, f(x)       -- additional results
f(x); return         -- results discarded
return x or f(x)     -- results adjusted to 1

2.5.9 函式定義 lua-function-define

函式定義的語法為
function ::= function funcbody
funcbody ::= ( [ parlist1 ] ) block end
以下語法糖簡化了函式定義
stat ::= function funcname funcbody
stat ::= local function Name funcbody
funcname ::= Name { . Name } [ : Name ]
陳述句
function f () body end
轉換為
f = function () body end
陳述句
function t.a.b.c.f () body end
轉換為
t.a.b.c.f = function () body end
陳述句
local function f () body end
轉換為
local f; f = function f () body end
而不是
local f = function f () body end
(只有當函式的主體包含對 f 的參考時,這才會產生差異。)
lua-closure
函式定義是一種可執行的表達式,其值具有 function 類型。當 Lua 預編譯一個程式碼塊時,它所有的函式主體也會被預編譯。然後,每當 Lua 執行函式定義時,該函式就會被實例化(或封閉)。這個函式實例(或閉包)是表達式的最終值。同一個函式的不同實例可能會參考不同的外部區域變數,並且可能具有不同的環境表。
參數的作用如同區域變數,並以引數值初始化。
parlist1 ::= namelist [ , ... ] | ...
lua-vararg
當一個函式被呼叫時,引數列表會被調整為與參數列表的長度相同,除非該函式是一個可變參數或變長引數函式,這類函式會在參數列表的末尾使用三個點(...)來表示。變長引數函式不會調整其引數列表;相反地,它會收集所有額外的引數,並透過一個也寫成三個點的變長引數表達式將它們提供給函式。此表達式的值是一個包含所有實際額外引數的列表,類似於具有多個結果的函式。如果變長引數表達式在另一個表達式內部或在表達式列表的中間使用,那麼它的返回列表會被調整為一個元素。如果該表達式作為表達式列表的最後一個元素使用,則不會進行調整(除非該呼叫被括在括號中)。
舉例來說,考慮以下定義
function f(a, b) end
function g(a, b, ...) end
function r() return 1,2,3 end
那麼,我們有以下從引數到參數以及到變長引數表達式的映射:
CALL            PARAMETERS
f(3)             a=3, b=nil
f(3, 4)          a=3, b=4
f(3, 4, 5)       a=3, b=4
f(r(), 10)       a=1, b=10
f(r())           a=1, b=2
g(3)             a=3, b=nil, ... -->  (nothing)
g(3, 4)          a=3, b=4,   ... -->  (nothing)
g(3, 4, 5, 8)    a=3, b=4,   ... -->  5  8
g(5, r())        a=5, b=1,   ... -->  2  3
結果是使用 return 語句返回的(請參閱 lua-control)。如果控制在未遇到 return 語句的情況下到達函式的結尾,則該函式將不返回任何結果。
lua-colonsyntax
冒號語法用於定義方法,也就是具有隱含的額外參數 self 的函式。因此,語句
function t.a.b.c:f ( params ) body end
是以下語法的簡寫:
t.a.b.c:f = function ( self, params ) body end

2.6 可見性規則 lua-visibility

Lua 是一種詞法作用域的語言。變數的作用域從它們宣告之後的第一個語句開始,並持續到包含該宣告的最內層區塊結束。請考慮以下範例:
x = 10                -- global variable
do                    -- new block
  local x = x         -- new `x`, with value 10
  print(x)            --> 10
  x = x+1
  do                  -- another block
    local x = x+1     -- another `x`
    print(x)          --> 12
  end
  print(x)            --> 11
end
print(x)              --> 10  (the global one)
請注意,在像 local x = x 這樣的宣告中,正在宣告的新 x 尚未進入作用域,因此第二個 x 指的是外部變數。
lua-upvalue
由於詞法作用域規則,在它們的作用域內定義的函式可以自由存取區域變數。在內部函式中使用的區域變數被稱為上值(upvalue),或內部函式內的外部區域變數。
請注意,每次執行區域語句都會定義新的區域變數。請考慮以下範例:
a = {}
local x = 20
for i=1,10 do
  local y = 0
  a[i] = function () y=y+1; return x+y end
end
迴圈會建立十個閉包(也就是匿名函式的十個實例)。這些閉包中的每一個都使用不同的 y 變數,而它們都共享同一個 x

2.7 錯誤處理 lua-errors

由於 Lua 是一種嵌入式的擴充語言,所有 Lua 動作都從主機程式中的 C 程式碼呼叫 Lua 函式庫的函式開始(請參閱 lua_pcall())。每當 Lua 編譯或執行期間發生錯誤時,控制權會返回給 C,C 可以採取適當的措施(例如印出錯誤訊息)。
Lua 程式碼可以透過呼叫 error 函式(請參閱 error())來明確地產生錯誤。如果您需要在 Lua 中捕獲錯誤,可以使用 pcall 函式(請參閱 pcall())。
Lua 中的每個值都可以有一個元表。這個元表是一個普通的 Lua 表格,它定義了原始表格和 userdata 在某些特殊操作下的行為。您可以透過在其元表中設定特定的欄位來變更物件行為的幾個方面。例如,當非數值是加法的運算元時,Lua 會檢查其元表中的 "__add" 欄位是否有函式。如果找到函式,Lua 會呼叫該函式來執行加法。
我們稱元表中的鍵為事件,而值為元方法。在先前的範例中,事件是「add」,而元方法是執行加法的函式。
您可以透過 getmetatable 函式(請參閱 getmetatable())查詢任何值的元表。
您可以透過 setmetatable 函式(請參閱 setmetatable())取代表格的元表。您無法從 Lua 變更其他類型的元表(使用除錯函式庫除外);您必須使用 C API 來進行變更。
表格和 userdata 有個別的元表(儘管多個表格和 userdata 可以共享同一個表格作為其元表);所有其他類型的值每個類型共享一個單一元表。因此,所有數字都有一個單一元表,所有字串也是如此,依此類推。
元表可以控制物件在算術運算、順序比較、串聯、長度運算和索引中的行為。元表也可以定義一個函式,當 userdata 被垃圾回收時呼叫。對於這些運算中的每一個,Lua 都會關聯一個稱為事件的特定鍵。當 Lua 對一個值執行這些運算中的一個時,它會檢查該值是否具有具有相應事件的元表。如果有,則與該鍵關聯的值(元方法)會控制 Lua 將如何執行該運算。
元表會控制接下來列出的運算。每個運算都以其對應的名稱識別。每個運算的鍵是一個字串,其名稱以兩個底線 __ 為前綴;例如,運算「add」的鍵是字串「__add」。這些運算的語意由描述直譯器如何執行該運算的 Lua 函式更好地解釋。
這裡在 Lua 中顯示的程式碼僅用於說明;實際行為是在直譯器中硬式編碼的,並且比此模擬效率高得多。這些描述中使用的所有函式(rawgettonumber 等)都在 lua-lib-core 中描述。特別是,為了檢索給定物件的元方法,我們使用表達式
metatable(obj)[event]
應該讀作
rawget(metatable(obj) or {}, event)
也就是說,存取元方法不會呼叫其他元方法,並且存取沒有元表的物件不會失敗(它只會產生 nil)。
「add」:__add()
------ + 運算。
下面的 getbinhandler 函式定義了 Lua 如何為二元運算選擇處理常式。首先,Lua 嘗試第一個運算元。如果其類型沒有為運算定義處理常式,則 Lua 會嘗試第二個運算元。
function getbinhandler (op1, op2, event)
  return metatable(op1)[event] or metatable(op2)[event]
end
透過使用此函式,op1 + op2 的行為是
function add_event (op1, op2)
  local o1, o2 = tonumber(op1), tonumber(op2)
  if o1 and o2 then  -- both operands are numeric?
    return o1 + o2   -- `+` here is the primitive `add`
  else  -- at least one of the operands is not numeric
    local h = getbinhandler(op1, op2, "__add")
    if h then
      -- call the handler with both operands
      return h(op1, op2)
    else  -- no handler available: default behavior
      error(...)
    end
  end
end
「sub」:__sub()
------ - 運算。行為類似於「add」運算。
「mul」:__mul()
------ * 運算。行為類似於「add」運算。
「div」:__div()
------ / 運算。行為類似於「add」運算。
「mod」:__mod()
------ % 運算。行為類似於「add」運算,運算 o1 - floor(o1/o2)*o2 作為原始運算。
「pow」:__pow()
------ ^(指數)運算。行為類似於「add」運算,使用函式 pow(來自 C 數學函式庫)作為原始運算。
「unm」:__unm()
------ 一元 - 運算。
function unm_event (op)
  local o = tonumber(op)
  if o then  -- operand is numeric?
    return -o  -- `-` here is the primitive `unm`
  else  -- the operand is not numeric.
    -- Try to get a handler from the operand
    local h = metatable(op).__unm
    if h then
      -- call the handler with the operand
      return h(op)
    else  -- no handler available: default behavior
      error(...)
    end
  end
end
「concat」:__concat()
--------- ..(串聯)運算。
function concat_event (op1, op2)
  if (type(op1) == "string" or type(op1) == "number") and
     (type(op2) == "string" or type(op2) == "number") then
    return op1 .. op2  -- primitive string concatenation
  else
    local h = getbinhandler(op1, op2, "__concat")
    if h then
      return h(op1, op2)
    else
      error(...)
    end
  end
end
「len」:__len()
------ # 運算。
function len_event (op)
  if type(op) == "string" then
    return strlen(op)         -- primitive string length
  elseif type(op) == "table" then
    return #op                -- primitive table length
  else
    local h = metatable(op).__len
    if h then
      -- call the handler with the operand
      return h(op)
    else  -- no handler available: default behavior
      error(...)
    end
  end
end
「eq」:__eq()
----- == 運算。
函式 getcomphandler 定義了 Lua 如何為比較運算子選擇元方法。只有當被比較的兩個物件具有相同的類型並且對於所選的運算具有相同的元方法時,才會選擇元方法。
function getcomphandler (op1, op2, event)
  if type(op1) ~= type(op2) then return nil end
  local mm1 = metatable(op1)[event]
  local mm2 = metatable(op2)[event]
  if mm1 == mm2 then return mm1 else return nil end
end
「eq」事件定義如下:
function eq_event (op1, op2)
  if type(op1) ~= type(op2) then  -- different types?
    return false   -- different objects
  end
  if op1 == op2 then   -- primitive equal?
    return true   -- objects are equal
  end
  -- try metamethod
  local h = getcomphandler(op1, op2, "__eq")
  if h then
    return h(op1, op2)
  else
    return false
  end
end
a ~= b 等同於 not (a == b)
「lt」:__lt()
----- < 運算。
function lt_event (op1, op2)
  if type(op1) == "number" and type(op2) == "number" then
    return op1 < op2   -- numeric comparison
  elseif type(op1) == "string" and type(op2) == "string" then
    return op1 < op2   -- lexicographic comparison
  else
    local h = getcomphandler(op1, op2, "__lt")
    if h then
      return h(op1, op2)
    else
      error(...);
    end
  end
end
a > b 等同於 b < a
「le」:__le()
----- <= 運算。
function le_event (op1, op2)
  if type(op1) == "number" and type(op2) == "number" then
    return op1 <= op2   -- numeric comparison
  elseif type(op1) == "string" and type(op2) == "string" then
    return op1 <= op2   -- lexicographic comparison
  else
    local h = getcomphandler(op1, op2, "__le")
    if h then
      return h(op1, op2)
    else
      h = getcomphandler(op1, op2, "__lt")
      if h then
        return not h(op2, op1)
      else
        error(...);
      end
    end
  end
end
a >= b 等同於 b <= a。請注意,在沒有「le」元方法的情況下,Lua 會嘗試「lt」,假設 a <= b 等同於 not (b < a)
「index」:__index()
-------- 索引存取 table[key]
function gettable_event (table, key)
  local h
  if type(table) == "table" then
    local v = rawget(table, key)
    if v ~= nil then return v end
    h = metatable(table).__index
    if h == nil then return nil end
  else
    h = metatable(table).__index
    if h == nil then
      error(...);
    end
  end
  if type(h) == "function" then
    return h(table, key)      -- call the handler
  else return h[key]          -- or repeat operation on it
end
「newindex」:__newindex()
----------- 索引指定 table[key] = value
function settable_event (table, key, value)
  local h
  if type(table) == "table" then
    local v = rawget(table, key)
    if v ~= nil then rawset(table, key, value); return end
    h = metatable(table).__newindex
    if h == nil then rawset(table, key, value); return end
  else
    h = metatable(table).__newindex
    if h == nil then
      error(...);
    end
  end
  if type(h) == "function" then
    return h(table, key,value)    -- call the handler
  else h[key] = value             -- or repeat operation on it
end
「call」:__call()
------- 當 Lua 呼叫一個值時被呼叫。
function function_event (func, ...)
  if type(func) == "function" then
    return func(...)   -- primitive call
  else
    local h = metatable(func).__call
    if h then
      return h(func, ...)
    else
      error(...)
    end
  end
end

2.9 環境 lua-environments

除了元表之外,類型為 thread、function 和 userdata 的物件還具有與它們關聯的另一個表格,稱為它們的環境。與元表類似,環境是規則的表格,多個物件可以共享相同的環境。
與 userdata 關聯的環境對 Lua 沒有意義。這僅是程式設計人員將表格與 userdata 關聯的便利功能。
與執行緒相關聯的環境稱為全域環境。它們會被當作其執行緒的預設環境,以及該執行緒所建立的非巢狀函式(透過 loadfile()loadstring()load()),並且可以由 C 程式碼直接存取(請參閱 lua-pseudoindex)。
與 C 函式相關聯的環境可以由 C 程式碼直接存取(請參閱 lua-pseudoindex)。它們會被當作該函式所建立的其他 C 函式的預設環境。
與 Lua 函式相關聯的環境用於解析函式內所有對全域變數的存取(請參閱 lua-variables)。它們會被當作該函式所建立的其他 Lua 函式的預設環境。
您可以透過呼叫 setfenv 來變更 Lua 函式或執行中執行緒的環境。您可以透過呼叫 getfenv 來取得 Lua 函式或執行中執行緒的環境(請參閱 lua_getfenv())。若要操作其他物件(userdata、C 函式、其他執行緒)的環境,您必須使用 C API。

2.10 垃圾收集 lua-gc

Lua 會執行自動記憶體管理。這表示您不必擔心為新物件配置記憶體,也不必擔心在不再需要物件時釋放記憶體。Lua 會藉由不時執行垃圾收集器來自動管理記憶體,以收集所有已死亡的物件(也就是,這些無法再從 Lua 存取的物件)。Lua 中的所有物件都受自動管理:表格、userdata、函式、執行緒和字串。
Lua 實作了一個增量標記清除收集器。它使用兩個數字來控制其垃圾收集週期:垃圾收集器的暫停時間和垃圾收集器的步進倍數。
垃圾收集器的暫停時間控制收集器在開始新週期之前等待的時間長度。數值越大,收集器的積極性就越低。小於 1 的數值表示收集器不會等待就開始新週期。數值 2 表示收集器會等待總記憶體使用量加倍,才會開始新週期。
步進倍數控制收集器相對於記憶體配置的相對速度。數值越大,收集器就越積極,但也會增加每個增量步驟的大小。小於 1 的數值會使收集器過慢,並可能導致收集器永遠無法完成一個週期。預設值 2 表示收集器的執行速度為記憶體配置速度的「兩倍」。
您可以透過在 C 中呼叫 lua_gc(請參閱 lua_gc())或在 Lua 中呼叫 collectgarbage(請參閱 collectgarbage())來變更這些數字。兩者都取得百分比點作為引數(因此 100 的引數表示實際值為 1)。您也可以使用這些函式直接控制收集器(例如,停止並重新啟動)。

2.10.1 垃圾收集元方法 lua-gc-meta

使用 C API,您可以為 userdata 設定垃圾收集元方法(請參閱 lua-metatable)。這些元方法也稱為終結器。終結器可讓您協調 Lua 的垃圾收集與外部資源管理(例如關閉檔案、網路或資料庫連線,或釋放您自己的記憶體)。
__gc
在其元表格中具有 __gc 欄位的垃圾 userdata 不會立即由垃圾收集器收集。相反地,Lua 會將它們放在一個列表中。在收集之後,Lua 會針對該列表中每個 userdata 執行相當於下列函式的動作
function gc_event (udata)
  local h = metatable(udata).__gc
  if h then
    h(udata)
  end
end
在每個垃圾收集週期結束時,會依其建立的反向順序呼叫 userdata 的終結器,這些終結器是在該週期中收集的。也就是說,第一個被呼叫的終結器是與程式中最後建立的 userdata 相關聯的終結器。

2.10.2 - 弱表格 lua-weaktable

弱表格是一個元素為弱參照的表格。弱參照會被垃圾收集器忽略。換句話說,如果對某個物件的唯一參照是弱參照,則垃圾收集器會收集此物件。
__mode
弱表格可以有弱鍵、弱值或兩者都有。具有弱鍵的表格允許收集其鍵,但會阻止收集其值。具有弱鍵和弱值的表格允許收集鍵和值。無論如何,如果收集了鍵或值,整個配對都會從表格中移除。表格的弱性由其元表格的 __mode 欄位的值控制。如果 __mode 欄位是一個包含字元 k 的字串,則表格中的鍵為弱鍵。如果 __mode 包含 v,則表格中的值為弱值。
在將表格用作元表格之後,您不應變更其 __mode 欄位的值。否則,由此元表格控制的表格的弱行為是未定義的。

2.11 協程 lua-coroutine

Lua 支援協程,也稱為協作多執行緒。Lua 中的協程代表一個獨立的執行緒。然而,與多執行緒系統中的執行緒不同,協程只會透過明確呼叫 yield 函式來暫停其執行。
您可以透過呼叫 coroutine.create 來建立協程(請參閱 coroutine.create())。其唯一引數是一個函式,該函式是協程的主要函式。create 函式只會建立一個新的協程並傳回其控制代碼(類型為 thread 的物件);它不會開始協程執行。
當您第一次呼叫 coroutine.resume(請參閱 coroutine.resume()),並將 coroutine.create 傳回的執行緒作為其第一個引數時,協程會從其主要函式的第一行開始執行。傳遞給 coroutine.resume 的額外引數會傳遞給協程主要函式。在協程開始執行後,它會執行到終止或 yields
協程可以透過兩種方式終止其執行:正常終止,當其主要函式傳回時(明確或隱式,在最後一條指令之後);以及異常終止,如果發生未受保護的錯誤。在第一種情況下,coroutine.resume 會傳回 true,以及協程主要函式傳回的任何值。在發生錯誤時,coroutine.resume 會傳回 false 以及錯誤訊息。
協程會透過呼叫 coroutine.yield 來 yield(請參閱 coroutine.yield())。當協程 yield 時,對應的 coroutine.resume 會立即傳回,即使 yield 發生在巢狀函式呼叫內(也就是說,不是在主要函式中,而是在主要函式直接或間接呼叫的函式中)。在 yield 的情況下,coroutine.resume 也會傳回 true,以及傳遞給 coroutine.yield 的任何值。下次您恢復同一個協程時,它會從它 yield 的點繼續執行,對 coroutine.yield 的呼叫會傳回傳遞給 coroutine.resume 的任何額外引數。
coroutine.create 類似,coroutine.wrap 函式(請參閱 coroutine.wrap())也會建立協程,但是它不是傳回協程本身,而是傳回一個函式,該函式在被呼叫時會恢復協程。傳遞給此函式的任何引數都會作為額外引數傳遞給 coroutine.resumecoroutine.wrap 會傳回 coroutine.resume 傳回的所有值,除了第一個值(布林錯誤碼)。與 coroutine.resume 不同,coroutine.wrap 不會捕獲錯誤;任何錯誤都會傳播給呼叫者。
舉例來說,請考慮以下程式碼
function foo1 (a)
  print("foo", a)
  return coroutine.yield(2*a)
end
co = coroutine.create(function (a,b)
      print("co-body", a, b)
      local r = foo1(a+1)
      print("co-body", r)
      local r, s = coroutine.yield(a+b, a-b)
      print("co-body", r, s)
      return b, "end"
end)
print("main", coroutine.resume(co, 1, 10))
print("main", coroutine.resume(co, "r"))
print("main", coroutine.resume(co, "x", "y"))
print("main", coroutine.resume(co, "x", "y"))
當您執行它時,它會產生以下輸出
co-body 1       10
foo     2
main    true    4
co-body r
main    true    11      -9
co-body x       y
main    true    10      end
main    false   cannot resume dead coroutine

3 應用程式介面 lua-API

本節說明 Lua 的 C API,也就是主機程式可用來與 Lua 通訊的 C 函式集。所有 API 函式以及相關的類型和常數都宣告在標頭檔 lua.h 中。
即使我們使用「函式」一詞,API 中的任何功能也可能會以 macro 的形式提供。所有這類巨集都只會精確使用每個引數一次(第一個引數除外,它始終是 Lua 狀態),因此不會產生隱藏的副作用。
與大多數 C 程式庫一樣,Lua API 函式不會檢查其引數的有效性或一致性。但是,您可以透過在檔案 luaconf.h 中使用巨集 luai_apicheck 的適當定義編譯 Lua 來變更此行為。

3.1 堆疊 lua-stack lua-apiStack

Lua 使用虛擬堆疊來在 C 之間傳遞值。此堆疊中的每個元素都代表一個 Lua 值(nil、數字、字串等)。
每當 Lua 呼叫 C 時,被呼叫的函式都會取得一個新的堆疊,該堆疊與先前的堆疊以及仍處於作用狀態的 C 函式的堆疊無關。此堆疊最初包含任何 C 函式的引數,並且 C 函式會將其結果推送到此處,以便傳回給呼叫者(請參閱 lua_CFunction)。
lua-stackindex
為方便起見,API 中的大多數查詢操作不遵循嚴格的堆疊規則。相反,它們可以使用索引來引用堆疊中的任何元素:正索引表示絕對堆疊位置(從 1 開始);負索引表示相對於堆疊頂部的偏移量。更具體地說,如果堆疊有 n 個元素,則索引 1 表示第一個元素(也就是說,第一個被推入堆疊的元素),而索引 n 表示最後一個元素;索引 -1 也表示最後一個元素(也就是說,位於頂部的元素),而索引 -n 表示第一個元素。如果索引位於 1 和堆疊頂部之間(也就是說,如果 1 <= abs(index) <= top),則我們稱該索引為有效索引。

3.2 堆疊大小 lua-apiStackSize

當您與 Lua API 互動時,您有責任確保一致性。特別是,您有責任控制堆疊溢位。您可以使用函式 lua_checkstack 來增加堆疊大小(請參閱 lua_checkstack())。
每當 Lua 呼叫 C 時,它都會確保至少有 LUA_MINSTACK 個堆疊位置可用。LUA_MINSTACK 定義為 20,因此通常您不必擔心堆疊空間,除非您的程式碼有迴圈將元素推入堆疊。
大多數查詢函式都接受可用堆疊空間內的任何值作為索引,也就是說,索引可達到您通過 lua_checkstack 設定的最大堆疊大小。此類索引稱為可接受索引。更正式地說,我們將可接受索引定義如下
(index < 0 && abs(index) <= top) || (index > 0 && index <= stackspace)
請注意,0 永遠不是可接受的索引。

3.3 偽索引 lua-pseudoindex

除非另有說明,否則任何接受有效索引的函式也可以使用偽索引呼叫,偽索引表示 C 程式碼可以存取但不在堆疊中的某些 Lua 值。偽索引用於存取執行緒環境、函式環境、登錄表以及 C 函式的向上值(請參閱 lua-cclosure)。
執行緒環境(全域變數的儲存位置)始終位於偽索引 LUA_GLOBALSINDEX。正在執行的 C 函式的環境始終位於偽索引 LUA_ENVIRONINDEX
若要存取和變更全域變數的值,您可以使用環境表上的正規表格操作。例如,若要存取全域變數的值,請執行以下操作
lua_getfield(L, LUA_GLOBALSINDEX, varname);

3.4 C 閉包 lua-cclosure

建立 C 函式時,可以將一些值與其關聯,從而建立 C 閉包;這些值稱為向上值,並且在每次呼叫該函式時都可供該函式存取(請參閱 lua_pushcclosure())。
每當呼叫 C 函式時,其向上值都位於特定的偽索引處。這些偽索引由巨集 lua_upvalueindex 產生。與函式關聯的第一個值位於位置 lua_upvalueindex(1),依此類推。任何對 lua_upvalueindex( n ) 的存取,其中 n 大於目前函式的向上值數量,都會產生一個可接受(但無效)的索引。

3.5 登錄表 lua-registry

Lua 提供了一個登錄表,這是一個預先定義的表格,任何 C 程式碼都可以使用它來儲存它需要儲存的任何 Lua 值。此表格始終位於偽索引 LUA_REGISTRYINDEX。任何 C 程式庫都可以將資料儲存到此表格中,但它應注意選擇與其他程式庫所用不同的索引鍵,以避免衝突。通常,您應使用包含您的程式庫名稱的字串或帶有 C 程式碼中 C 物件位址的輕量使用者資料作為索引鍵。
登錄表中的整數索引鍵由輔助程式庫實作的參考機制使用,因此不應用於其他目的。

3.6 C 中的錯誤處理 lua-apiError

在內部,Lua 使用 C longjmp 功能來處理錯誤。(如果您使用 C++,也可以選擇使用例外狀況;請參閱檔案 luaconf.h。)當 Lua 面臨任何錯誤(例如記憶體配置錯誤、類型錯誤、語法錯誤和執行階段錯誤)時,它會引發錯誤;也就是說,它會執行長跳躍。受保護的環境使用 setjmp 來設定恢復點;任何錯誤都會跳到最近的活動恢復點。
API 中的幾乎所有函式都可能引發錯誤,例如由於記憶體配置錯誤。以下函式在受保護的模式下執行(也就是說,它們會建立一個受保護的環境來執行),因此它們永遠不會引發錯誤:lua_newstatelua_closelua_loadlua_pcalllua_cpcall(請參閱 lua_newstate()lua_close()lua_load()lua_pcall()lua_cpcall())。
在 C 函式內部,您可以通過呼叫 lua_error 來引發錯誤(請參閱 lua_error())。

3.7 函式和類型 lua-apiFunctions

在此我們按字母順序列出 C API 中的所有函式和類型。
lua_Alloc lua_Alloc
typedef void * (*lua_Alloc) (void *ud,
                             void *ptr,
                             size_t osize,
                             size_t nsize);
Lua 狀態使用的記憶體配置函式的類型。配置器函式必須提供類似於 realloc 的功能,但並不完全相同。其引數為 ud,一個傳遞給 lua_newstate 的不透明指標(請參閱 lua_newstate());ptr,一個指向要配置/重新配置/釋放的區塊的指標;osize,區塊的原始大小;nsize,區塊的新大小。當且僅當 osize 為零時,ptr 才為 NULL。當 nsize 為零時,配置器必須傳回 NULL;如果 osize 不為零,則它應釋放 ptr 指向的區塊。當 nsize 不為零時,當且僅當配置器無法滿足請求時,配置器才會傳回 NULL。當 nsize 不為零且 osize 為零時,配置器應像 malloc 一樣運作。當 nsizeosize 都不為零時,配置器應像 realloc 一樣運作。Lua 假設當 `osize >= nsize` 時,配置器永遠不會失敗。
以下是配置器函式的簡單實作。它在輔助程式庫中被 luaL_newstate 使用(請參閱 luaL_newstate())。
static void *l_alloc (void *ud, void *ptr, size_t osize,
                                           size_t nsize) {
  (void)ud;  (void)osize;  /* not used */
  if (nsize == 0) {
    free(ptr);
    return NULL;
  }
  else
    return realloc(ptr, nsize);
}
此程式碼假設 free(NULL) 沒有效果,且 realloc(NULL, size) 等同於 malloc(size)。ANSI C 確保這兩種行為。
lua_atpanic lua_atpanic()
lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf);
設定新的 panic 函式並傳回舊函式。
如果錯誤發生在任何受保護的環境之外,Lua 會呼叫一個 panic function,然後呼叫 exit(EXIT_FAILURE),從而結束主機應用程式。您的 panic 函式可以透過永不傳回(例如,執行長跳躍)來避免此結束。
panic 函式可以存取堆疊頂部的錯誤訊息。
lua_call lua_call()
void lua_call (lua_State *L, int nargs, int nresults);
呼叫函式。
若要呼叫函式,您必須使用以下協定:首先,將要呼叫的函式推入堆疊;然後,按直接順序推入函式的引數;也就是說,先推入第一個引數。最後,您呼叫 lua_callnargs 是您推入堆疊的引數數量。呼叫函式時,會從堆疊中彈出所有引數和函式值。函式傳回時,會將函式結果推入堆疊。除非 nresultsLUA_MULTRET,否則結果數量會調整為 nresults。在這種情況下,會推入函式的所有結果。Lua 會確保傳回的值符合堆疊空間。函式結果會按直接順序推入堆疊(先推入第一個結果),以便在呼叫後,最後一個結果位於堆疊頂部。
被呼叫函式內的任何錯誤都會向上傳播(使用 longjmp)。
以下範例顯示主機程式如何執行與以下 Lua 程式碼等效的操作
a = f("how", t.x, 14)
以下是以 C 語言編寫的範例
lua_getfield(L, LUA_GLOBALSINDEX, "f"); // function to be called
lua_pushstring(L, "how");                        // 1st argument
lua_getfield(L, LUA_GLOBALSINDEX, "t");   // table to be indexed
lua_getfield(L, -1, "x");        // push result of t.x (2nd arg)
lua_remove(L, -2);                  // remove 't' from the stack
lua_pushinteger(L, 14);                          // 3rd argument
lua_call(L, 3, 1);     // call 'f' with 3 arguments and 1 result
lua_setfield(L, LUA_GLOBALSINDEX, "a");        // set global 'a'
請注意,上面的程式碼是「平衡的」:在其結尾,堆疊會恢復到其原始組態。這被認為是良好的程式設計實務。
lua_CFunction lua-cfunction lua_CFunction
typedef int (*lua_CFunction) (lua_State *L);
C 函式的類型。
為了與 Lua 正確通訊,C 函式必須使用以下協定,該協定定義了引數和結果的傳遞方式:C 函式按直接順序(先推入第一個引數)從 Lua 的堆疊中接收其引數。因此,當函式開始時,lua_gettop(L)(請參閱 lua_gettop())會傳回函式接收的引數數量。第一個引數(如果有的話)位於索引 1,而最後一個引數位於索引 lua_gettop(L)。若要將值傳回 Lua,C 函式只需按直接順序(先推入第一個結果)將它們推入堆疊,然後傳回結果的數量。堆疊中低於結果的任何其他值都會被 Lua 正確丟棄。像 Lua 函式一樣,Lua 呼叫的 C 函式也可以傳回多個結果。
lua-cfunctionexample
例如,以下函式接收可變數量的數字引數並傳回它們的平均值和總和
static int foo (lua_State *L) {
  int n = lua_gettop(L);    /* number of arguments */
  lua_Number sum = 0;
  int i;
  for (i = 1; i &lt;= n; i++) {
    if (!lua_isnumber(L, i)) {
      lua_pushstring(L, "incorrect argument");
      lua_error(L);
    }
    sum += lua_tonumber(L, i);
  }
  lua_pushnumber(L, sum/n); /* first result */
  lua_pushnumber(L, sum);   /* second result */
  return 2;                 /* number of results */
}
lua_checkstack lua_checkstack()
int lua_checkstack (lua_State *L, int extra);
確保堆疊中至少有 extra 個可用的堆疊插槽。如果它無法將堆疊擴展到該大小,則會傳回 false。此函式永遠不會縮小堆疊;如果堆疊已經大於新大小,則它會保持不變。
lua_close lua_close()
void lua_close (lua_State *L);
銷毀給定 Lua 狀態中的所有物件(如果有的話,則呼叫對應的垃圾收集元方法)並釋放此狀態使用的所有動態記憶體。在多個平台上,您可能不需要呼叫此函式,因為當主機程式結束時,所有資源都會自然釋放。另一方面,長時間執行的程式,例如守護程式或網頁伺服器,可能需要在不需要狀態時立即釋放它們,以避免變得太大。
lua_concat lua_concat()
void lua_concat (lua_State *L, int n);
將堆疊頂端的 n 個值串接起來,並將這些值彈出堆疊,然後將結果留在頂端。如果 n 為 1,則結果是堆疊上的單一字串(也就是說,此函數不執行任何操作);如果 n 為 0,則結果為空字串。串接會遵循 Lua 的一般語義進行(請參閱 lua-concat)。
lua_cpcall lua_cpcall()
int lua_cpcall (lua_State *L, lua_CFunction func, void *ud);
在保護模式下呼叫 C 函數 funcfunc 的堆疊中一開始只有一個元素,即包含 ud 的輕型使用者資料。如果發生錯誤,lua_cpcall 會傳回與 lua_pcall 相同的錯誤碼(請參閱 lua_pcall()),並將錯誤物件放在堆疊頂端;否則,它會傳回零,且不會變更堆疊。func 傳回的所有值都會被捨棄。
lua_createtable lua_createtable()
void lua_createtable (lua_State *L, int narr, int nrec);
建立一個新的空表格,並將其推入堆疊。這個新表格會預先配置空間給 narr 個陣列元素和 nrec 個非陣列元素。當您確切知道表格會有多少元素時,這種預先配置會很有用。否則,您可以使用函數 lua_newtable(請參閱 lua_newtable())。
lua_dump lua_dump()
int lua_dump (lua_State *L, lua_Writer writer, void *data);
將函數轉儲為二進位區塊。接收堆疊頂端的 Lua 函數,並產生一個二進位區塊,如果重新載入,則會產生與轉儲的函數等效的函數。當產生區塊的各部分時,lua_dump 會使用給定的 data 呼叫函數 writer(請參閱 lua_Writer)來寫入它們。
傳回的值是最後一次呼叫 writer 時傳回的錯誤碼;0 表示沒有錯誤。
此函數不會從堆疊中彈出 Lua 函數。
lua_equal lua_equal()
int lua_equal (lua_State *L, int index1, int index2);
如果可接受索引 index1index2 中的兩個值相等,則傳回 1,遵循 Lua == 運算子的語義(也就是說,可能會呼叫元方法)。否則傳回 0。如果任何索引無效,也會傳回 0。
lua_error lua_error()
int lua_error (lua_State *L);
產生 Lua 錯誤。錯誤訊息(實際上可以是任何類型的 Lua 值)必須在堆疊頂端。此函數會進行長跳躍,因此永遠不會傳回(請參閱 luaL_error())。
lua_gc lua_gc()
int lua_gc (lua_State *L, int what, int data);
控制垃圾收集器。
此函數會根據參數 what 的值執行數項工作
LUA_GCSTOP 停止垃圾收集器。
LUA_GCRESTART 重新啟動垃圾收集器。
LUA_GCCOLLECT 執行完整的垃圾收集週期。
LUA_GCCOUNT 傳回 Lua 目前使用的記憶體量(以 K 位元組為單位)。
LUA_GCCOUNTB 傳回 Lua 目前使用的記憶體位元組數除以 1024 的餘數。
LUA_GCSTEP 執行垃圾收集的增量步驟。步驟「大小」由 data 控制(較大的值表示較多的步驟),其方式未指定。如果您想要控制步驟大小,則必須以實驗方式調整 data 的值。如果步驟完成垃圾收集週期,則函數會傳回 1。
LUA_GCSETPAUSEdata /100 設定為收集器 pause 的新值(請參閱 lua-gc)。函數會傳回先前 pause 的值。
LUA_GCSETSTEPMULdata /100 設定為收集器 step multiplier 的新值(請參閱 lua-gc)。函數會傳回先前 step multiplier 的值。
lua_getallocf lua_getallocf()
lua_Alloc lua_getallocf (lua_State *L, void **ud);
傳回給定狀態的記憶體配置函數。如果 ud 不是 NULL,則 Lua 會在 *ud 中儲存傳遞給 lua_newstate 的不透明指標(請參閱 lua_newstate())。
lua_getfenv lua_getfenv()
void lua_getfenv (lua_State *L, int index);
將給定索引處的值的環境表格推入堆疊。
lua_getfield lua_getfield()
void lua_getfield (lua_State *L, int index, const char *k);
將值 t[k] 推入堆疊,其中 t 是給定有效索引 index 處的值。如同在 Lua 中,此函數可能會觸發「index」事件的元方法(請參閱 lua-metatable)。
lua_getglobal lua_getglobal()
void lua_getglobal (lua_State *L, const char *name);
將全域變數 name 的值推入堆疊。它定義為巨集
#define lua_getglobal(L,s)  lua_getfield(L, LUA_GLOBALSINDEX, s)
lua_getmetatable lua_getmetatable()
int lua_getmetatable (lua_State *L, int index);
將給定可接受索引處的值的元表格推入堆疊。如果索引無效,或值沒有元表格,則函數會傳回 0,且不會將任何內容推入堆疊。
lua_gettable lua_gettable()
void lua_gettable (lua_State *L, int index);
將值 t[k] 推入堆疊,其中 t 是給定有效索引 index 處的值,而 k 是堆疊頂端的值。
此函數會從堆疊中彈出索引鍵(將結果值放在其位置)。如同在 Lua 中,此函數可能會觸發「index」事件的元方法(請參閱 lua-metatable)。
lua_gettop lua_gettop()
int lua_gettop (lua_State *L);
傳回堆疊中頂端元素的索引。由於索引從 1 開始,因此此結果等於堆疊中的元素數(因此 0 表示空堆疊)。
lua_insert lua_insert()
void lua_insert (lua_State *L, int index);
將頂端元素移動到給定的有效索引,向上移動此索引上方的元素以開啟空間。無法使用虛擬索引呼叫,因為虛擬索引不是實際的堆疊位置。
lua_Integer lua_Integer
typedef ptrdiff_t lua_Integer;
Lua API 用於表示整數值的類型。
預設情況下,它是 ptrdiff_t,這通常是機器「舒適」處理的最大整數類型。
lua_isboolean lua_isboolean()
int lua_isboolean (lua_State *L, int index);
如果給定可接受索引處的值的類型為布林值,則傳回 1,否則傳回 0。
lua_iscfunction lua_iscfunction()
int lua_iscfunction (lua_State *L, int index);
如果給定可接受索引處的值是 C 函數,則傳回 1,否則傳回 0。
lua_isfunction lua_isfunction()
int lua_isfunction (lua_State *L, int index);
如果給定可接受索引處的值是函數(C 或 Lua),則傳回 1,否則傳回 0。
lua_islightuserdata lua_islightuserdata()
int lua_islightuserdata (lua_State *L, int index);
如果給定可接受索引處的值是輕型使用者資料,則傳回 1,否則傳回 0。
lua_isnil lua_isnil()
int lua_isnil (lua_State *L, int index);
如果給定可接受索引處的值是 nil,則傳回 1,否則傳回 0。
lua_isnumber lua_isnumber()
int lua_isnumber (lua_State *L, int index);
如果給定可接受索引處的值是數字或可轉換為數字的字串,則傳回 1,否則傳回 0。
lua_isstring lua_isstring()
int lua_isstring (lua_State *L, int index);
如果給定可接受索引處的值是字串或數字(始終可以轉換為字串),則傳回 1,否則傳回 0。
lua_istable lua_istable()
int lua_istable (lua_State *L, int index);
如果給定可接受索引處的值是表格,則傳回 1,否則傳回 0。
lua_isthread lua_isthread()
int lua_isthread (lua_State *L, int index);
如果給定可接受索引處的值是執行緒,則傳回 1,否則傳回 0。
lua_isuserdata lua_isuserdata()
int lua_isuserdata (lua_State *L, int index);
如果給定可接受索引處的值是使用者資料(完整或輕型),則傳回 1,否則傳回 0。
lua_lessthan lua_lessthan()
int lua_lessthan (lua_State *L, int index1, int index2);
如果可接受索引 index1 處的值小於可接受索引 index2 處的值,則傳回 1,遵循 Lua < 運算子的語義(也就是說,可能會呼叫元方法)。否則傳回 0。如果任何索引無效,也會傳回 0。
lua_load lua_load()
int lua_load (lua_State *L,
              lua_Reader reader,
              void *data,
              const char *chunkname);
載入 Lua 區塊。如果沒有錯誤,lua_load 會將編譯的區塊做為 Lua 函數推入堆疊頂端。否則,它會推入錯誤訊息。lua_load 的傳回值如下
0:沒有錯誤;
LUA_ERRSYNTAX:預先編譯期間的語法錯誤;
LUA_ERRMEM:記憶體配置錯誤。
此函數只會載入區塊;不會執行它。
lua_load 會自動偵測區塊是文字還是二進位,並據此載入(請參閱程式 luac)。
lua_load 函數會使用使用者提供的 reader 函數來讀取區塊(請參閱 lua_Reader)。data 引數是不透明值,會傳遞給 reader 函數。
chunkname 引數會為區塊提供名稱,該名稱用於錯誤訊息和偵錯資訊中(請參閱 lua-apiDebug)。
lua_newstate lua_newstate()
lua_State *lua_newstate (lua_Alloc f, void *ud);
建立新的獨立狀態。如果無法建立狀態(由於記憶體不足),則傳回 NULL。引數 f 是配置器函數;Lua 會透過此函數執行此狀態的所有記憶體配置。第二個引數 ud 是不透明指標,Lua 只會在每次呼叫時將其傳遞給配置器。
lua_newtable lua_newtable()
void lua_newtable (lua_State *L);
建立一個新的空表格並將其推入堆疊。它等同於 lua_createtable(L, 0, 0)(請參閱 lua_createtable())。
lua_newthread lua_newthread()
lua_State *lua_newthread (lua_State *L);
建立一個新的執行緒,將其推入堆疊,並回傳一個指向 lua_State(請參閱 lua_State)的指標,該指標代表此新的執行緒。此函式回傳的新狀態與原始狀態共享所有全域物件(例如表格),但具有獨立的執行堆疊。
沒有明確的函式可以關閉或銷毀執行緒。執行緒會像任何 Lua 物件一樣進行垃圾回收。
lua_newuserdata lua_newuserdata()
void *lua_newuserdata (lua_State *L, size_t size);
此函式會配置一個具有指定大小的新記憶體區塊,將一個新的完整 userdata(使用者資料)與區塊位址推入堆疊,並回傳此位址。userdata
Userdata 代表 Lua 中的 C 值。完整的 userdata 代表一個記憶體區塊。它是一個物件(類似於表格):您必須建立它,它可以有自己的元表格,並且您可以偵測到何時被回收。一個完整的 userdata 只與它自己相等(在原始相等性下)。
當 Lua 回收具有 gc 元方法的完整 userdata 時,Lua 會呼叫元方法並將 userdata 標記為已完成。當此 userdata 再次被回收時,Lua 會釋放其對應的記憶體。
lua_next lua_next()
int lua_next (lua_State *L, int index);
從堆疊中彈出一個鍵,並從指定索引處的表格中推入一個鍵值對(給定鍵之後的「下一個」鍵值對)。如果表格中沒有更多元素,則 lua_next 會回傳 0(且不推入任何內容)。
lua-tabletraversal
典型的遍歷方式如下
/* table is in the stack at index 't' */
lua_pushnil(L);  /* first key */
while (lua_next(L, t) != 0) {
  /* uses 'key' (at index -2) and 'value' (at index -1) */
  printf("%s - %s\n",
         lua_typename(L, lua_type(L, -2)),
         lua_typename(L, lua_type(L, -1)));
  /* removes 'value'; keeps 'key' for next iteration */
  lua_pop(L, 1);
}
在遍歷表格時,請勿直接對鍵呼叫 lua_tolstring(請參閱 lua_tolstring()),除非您知道該鍵實際上是一個字串。請回想一下,lua_tolstring變更給定索引處的值;這會混淆對 lua_next 的下一次呼叫。
lua_Number lua_Number
typedef double lua_Number;
Lua 中數字的類型。預設情況下,它是 double,但可以在 luaconf.h 中變更。
透過組態檔,您可以變更 Lua 以使用另一種類型來表示數字(例如,float 或 long)。
lua_objlen lua_objlen()
size_t lua_objlen (lua_State *L, int index);
回傳給定可接受索引處的值的「長度」:對於字串,這是字串長度;對於表格,這是長度運算符 (#) 的結果;對於 userdata,這是為 userdata 配置的記憶體區塊大小;對於其他值,則為 0。
lua_pcall lua_pcall()
lua_pcall (lua_State *L, int nargs, int nresults, int errfunc);
以保護模式呼叫函式。
nargsnresults 的含義與 lua_call(請參閱 lua_call())中的含義相同。如果在呼叫期間沒有錯誤,則 lua_pcall 的行為與 lua_call 完全相同。但是,如果有任何錯誤,lua_pcall 會捕獲它,在堆疊上推入一個值(錯誤訊息),並回傳一個錯誤碼。與 lua_call 一樣,lua_pcall 總是會從堆疊中移除函式及其引數。
如果 errfunc 為 0,則堆疊上回傳的錯誤訊息與原始錯誤訊息完全相同。否則,errfunc錯誤 處理函式 的堆疊索引。(在目前的實作中,此索引不能是虛擬索引。)在發生執行階段錯誤時,將使用錯誤訊息呼叫此函式,並且其回傳值將是 lua_pcall 在堆疊上回傳的訊息。
通常,錯誤處理函式用於將更多偵錯資訊新增到錯誤訊息中,例如堆疊回溯。由於在 lua_pcall 回傳後,堆疊已解除,因此無法收集此類資訊。
lua_pcall 函式在成功時回傳 0,或回傳以下錯誤碼之一(在 lua.h 中定義)
LUA_ERRRUN 執行階段錯誤。
LUA_ERRMEM 記憶體配置錯誤。對於此類錯誤,Lua 不會呼叫錯誤處理函式。
LUA_ERRERR 執行錯誤處理函式時發生錯誤。
lua_pop lua_pop()
void lua_pop (lua_State *L, int n);
從堆疊中彈出 n 個元素。
lua_pushboolean lua_pushboolean()
void lua_pushboolean (lua_State *L, int b);
將一個具有值 b 的布林值推入堆疊。
lua_pushcclosure lua_pushcclosure()
void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);
將一個新的 C 閉包推入堆疊。
建立 C 函式時,可以將一些值與其關聯,從而建立一個 C 閉包(請參閱 lua-cclosure);然後,每當呼叫該函式時,該函式都可以存取這些值。若要將值與 C 函式關聯,首先應將這些值推入堆疊(當有多個值時,先推入第一個值)。然後呼叫 lua_pushcclosure 以建立 C 函式並將其推入堆疊,參數 n 會告知應與該函式關聯多少個值。lua_pushcclosure 也會從堆疊中彈出這些值。
lua_pushcfunction lua_pushcfunction()
void lua_pushcfunction (lua_State *L, lua_CFunction f);
將 C 函式推入堆疊。此函式會接收指向 C 函式的指標,並將類型為 function 的 Lua 值推入堆疊,當呼叫該值時,將會調用對應的 C 函式。
任何要在 Lua 中註冊的函式都必須遵循正確的協定來接收其參數並回傳其結果(請參閱 lua_CFunction)。
lua_pushcfunction 定義為巨集
#define lua_pushcfunction(L,f)  lua_pushcclosure(L,f,0)
lua_pushfstring lua_pushfstring()
const char *lua_pushfstring (lua_State *L, const char *fmt, ...);
將格式化的字串推入堆疊並回傳指向該字串的指標。它類似於 C 函式 sprintf,但有一些重要的差異
您不必為結果配置空間:結果是一個 Lua 字串,Lua 會負責記憶體配置(以及透過垃圾回收進行釋放)。
轉換指定符相當有限。沒有標誌、寬度或精度。轉換指定符只能是 %%(在字串中插入 %)、%s(插入以 null 終止的字串,沒有大小限制)、%f(插入 lua_Number)、%p(以十六進位數字插入指標)、%d(插入 int)和 %c(將 int 作為字元插入)。
lua_pushinteger lua_pushinteger()
void lua_pushinteger (lua_State *L, lua_Integer n);
將一個具有值 n 的數字推入堆疊。
lua_pushlightuserdata lua_pushlightuserdata()
void lua_pushlightuserdata (lua_State *L, void *p);
將一個輕量級 userdata 推入堆疊。lua-lightuserdata
Userdata 代表 Lua 中的 C 值。輕量級 userdata 代表一個指標。它是一個值(類似於數字):您不會建立它,它沒有個別的元表格,並且不會被回收(因為它從未被建立)。輕量級 userdata 與具有相同 C 位址的「任何」輕量級 userdata 相等。
lua_pushlstring lua_pushlstring()
void lua_pushlstring (lua_State *L, const char *s, size_t len);
將由 s 指向的、大小為 len 的字串推入堆疊。Lua 會建立(或重複使用)給定字串的內部副本,因此在函式回傳後,可以立即釋放或重複使用 s 處的記憶體。字串可以包含嵌入的零。
lua_pushnil lua_pushnil()
void lua_pushnil (lua_State *L);
將 nil 值推入堆疊。
lua_pushnumber lua_pushnumber()
void lua_pushnumber (lua_State *L, lua_Number n);
將一個具有值 n 的數字推入堆疊。
lua_pushstring lua_pushstring()
void lua_pushstring (lua_State *L, const char *s);
將由 s 指向的、以 null 結尾的字串推入堆疊。Lua 會建立(或重複使用)給定字串的內部副本,因此在函式回傳後,可以立即釋放或重複使用 s 處的記憶體。字串不能包含嵌入的零;假設它在第一個零處結束。
lua_pushthread lua_pushthread()
int lua_pushthread (lua_State *L);
將由 L 代表的執行緒推入堆疊。如果此執行緒是其狀態的主要執行緒,則回傳 1。
lua_pushvalue lua_pushvalue()
void lua_pushvalue (lua_State *L, int index);
將給定有效索引處的元素的副本推入堆疊。
lua_pushvfstring lua_pushvfstring()
const char *lua_pushvfstring (lua_State *L,
                              const char *fmt,
                              va_list argp);
等同於 lua_pushfstring(請參閱 lua_pushfstring()),只是它接收 va_list 而不是可變數量的引數。
lua_rawequal lua_rawequal()
int lua_rawequal (lua_State *L, int index1, int index2);
如果可接受索引 index1index2 中的兩個值在原始意義上相等(即,不呼叫元方法),則回傳 1。否則回傳 0。如果任何索引無效,也回傳 0。
lua_rawget lua_rawget()
void lua_rawget (lua_State *L, int index);
lua_gettable(請參閱 lua_gettable())類似,但會執行原始存取(即,不使用元方法)。
lua_rawgeti lua_rawgeti()
void lua_rawgeti (lua_State *L, int index, int n);
將值 t[n] 推入堆疊,其中 t 是給定有效索引 index 處的值。存取是原始存取;也就是說,它不會調用元方法。
lua_rawset lua_rawset()
void lua_rawset (lua_State *L, int index);
lua_settable(請參閱 lua_settable())類似,但會執行原始指派(即,不使用元方法)。
lua_rawseti lua_rawseti()
void lua_rawseti (lua_State *L, int index, int n);
執行等同於 t[n] = v 的操作,其中 t 是給定有效索引 index 處的值,而 v 是堆疊頂端的值。
此函式會從堆疊中彈出該值。指派是原始指派;也就是說,它不會調用元方法。
lua_Reader lua_Reader
typedef const char * (*lua_Reader) (lua_State *L,
                                    void *data,
                                    size_t *size);
lua_load(請參閱 lua_load())使用的讀取器函式。每當需要區塊的另一部分時,lua_load 會呼叫讀取器,並傳遞其 data 參數。讀取器必須回傳一個指向具有區塊新部分的記憶體區塊的指標,並將 size 設定為區塊大小。該區塊必須存在,直到再次呼叫讀取器函式為止。若要發出區塊結束的訊號,讀取器必須回傳 NULL。讀取器函式可以回傳任何大小大於零的部分。
lua_register lua_register()
void lua_register (lua_State *L,
                   const char *name,
                   lua_CFunction f);
將 C 函式 f 設定為全域 name 的新值。它定義為巨集
#define lua_register(L,n,f) \
       (lua_pushcfunction(L, f), lua_setglobal(L, n))
lua_remove lua_remove()
void lua_remove (lua_State *L, int index);
移除指定有效索引位置的元素,並將該索引之上的元素向下移動以填補空隙。不能使用虛擬索引呼叫此函數,因為虛擬索引並非實際的堆疊位置。
lua_replace lua_replace()
void lua_replace (lua_State *L, int index);
將堆疊頂端的元素移動到指定位置 (並將其彈出),不移動其他任何元素 (因此會取代指定位置的值)。
lua_resume lua_resume()
int lua_resume (lua_State *L, int narg);
在給定的執行緒中啟動並恢復協程。
若要啟動協程,您首先要建立一個新的執行緒 (請參閱 lua_newthread());然後將主函數和任何引數推入其堆疊中;接著使用引數數量 narg 呼叫 lua_resume (請參閱 lua_resume())。當協程暫停或完成執行時,此呼叫會返回。當它返回時,堆疊會包含所有傳遞給 lua_yield (請參閱 lua_yield()) 的值,或主體函數返回的所有值。如果協程暫停,lua_resume 會返回 LUA_YIELD;如果協程在沒有錯誤的情況下完成執行,則返回 0;如果發生錯誤,則返回錯誤代碼 (請參閱 lua_pcall())。發生錯誤時,堆疊不會回溯,因此您可以在其上使用除錯 API。錯誤訊息位於堆疊頂端。若要重新啟動協程,您只需將要作為 lua_yield 結果傳遞的值放入其堆疊中,然後呼叫 lua_resume
lua_setallocf lua_setallocf()
void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
將給定狀態的記憶體配置器函數變更為具有使用者資料 udf
lua_setfenv lua_setfenv()
int lua_setfenv (lua_State *L, int index);
從堆疊中彈出一個表格,並將其設定為指定索引處值的新環境。如果指定索引處的值既不是函數、執行緒也不是使用者資料,則 lua_setfenv 會返回 0。否則,它會返回 1。
lua_setfield lua_setfield()
void lua_setfield (lua_State *L, int index, const char *k);
等同於 t[k] = v,其中 t 是指定有效索引 index 處的值,而 v 是堆疊頂端的值。
此函數會從堆疊中彈出值。與 Lua 中一樣,此函數可能會觸發 "newindex" 事件的中介方法 (請參閱 lua-metatable)。
lua_setglobal lua_setglobal()
void lua_setglobal (lua_State *L, const char *name);
從堆疊中彈出一個值,並將其設定為全域變數 name 的新值。它被定義為巨集
#define lua_setglobal(L,s)   lua_setfield(L, LUA_GLOBALSINDEX, s)
lua_setmetatable lua_setmetatable()
int lua_setmetatable (lua_State *L, int index);
從堆疊中彈出一個表格,並將其設定為指定可接受索引處值的新中介表格。
lua_settable lua_settable()
void lua_settable (lua_State *L, int index);
等同於 t[k] = v,其中 t 是指定有效索引 index 處的值,v 是堆疊頂端的值,而 k 是緊接在頂端下方的值。
此函數會從堆疊中彈出鍵和值。與 Lua 中一樣,此函數可能會觸發 "newindex" 事件的中介方法 (請參閱 lua-metatable)。
lua_settop lua_settop()
void lua_settop (lua_State *L, int index);
接受任何可接受的索引或 0,並將堆疊頂端設定為此索引。如果新頂端大於舊頂端,則新元素會以 nil 填滿。如果 index 為 0,則會移除所有堆疊元素。
lua_State lua_State
typedef struct lua_State lua_State;
不透明的結構,用於保留 Lua 直譯器的整個狀態。Lua 程式庫是完全可重入的:它沒有全域變數。有關狀態的所有資訊都保存在此結構中。
此狀態的指標必須作為程式庫中每個函數的第一個引數傳遞,除了 lua_newstate (請參閱 lua_newstate()) 之外,後者會從頭開始建立 Lua 狀態。
lua_status lua_status()
int lua_status (lua_State *L);
返回執行緒 L 的狀態。
對於正常執行緒,狀態可以是 0;如果執行緒在執行時發生錯誤而結束,則為錯誤代碼;如果執行緒暫停,則為 LUA_YIELD
lua_toboolean lua_toboolean()
int lua_toboolean (lua_State *L, int index);
將指定可接受索引處的 Lua 值轉換為 C 布林值 (0 或 1)。與 Lua 中的所有測試一樣,lua_toboolean 對於任何不同於 falsenil 的 Lua 值都會返回 1;否則,它會返回 0。當使用無效的索引呼叫時,它也會返回 0。(如果您只想接受實際的布林值,請使用 lua_isboolean lua_isboolean() 來測試值的類型。)
lua_tocfunction lua_tocfunction()
lua_CFunction lua_tocfunction (lua_State *L, int index);
將指定可接受索引處的值轉換為 C 函數。該值必須為 C 函數;否則,它會返回 NULL
lua_tointeger lua_tointeger()
lua_Integer lua_tointeger (lua_State *L, int idx);
將指定可接受索引處的 Lua 值轉換為帶正負號的整數類型 lua_Integer (請參閱 lua_Integer)。Lua 值必須是數字或可轉換為數字的字串 (請參閱 lua-coercion);否則,lua_tointeger 會返回 0。
如果該數字不是整數,則會以某種未指定的方式截斷。
lua_tolstring lua_tolstring()
const char *lua_tolstring (lua_State *L, int index, size_t *len);
將指定可接受索引處的 Lua 值轉換為 C 字串。如果 len 不是 NULL,它還會將 *len 設定為字串長度。Lua 值必須是字串或數字;否則,該函數會返回 NULL。如果值是數字,則 lua_tolstring 也會將堆疊中的實際值變更為字串。(當 lua_tolstring 在表格遍歷期間應用於鍵時,此變更會使 lua_next lua_next() 感到困惑。)
lua_tolstring 會返回指向 Lua 狀態內字串的完全對齊的指標。此字串在最後一個字元之後 (如在 C 中) 總是會有一個零 (\0),但在其主體中可能包含其他零。由於 Lua 具有垃圾回收功能,因此無法保證在從堆疊中移除相應的值後,lua_tolstring 返回的指標仍然有效。
lua_tonumber lua_tonumber()
lua_Number lua_tonumber (lua_State *L, int index);
將指定可接受索引處的 Lua 值轉換為 C 類型 lua_Number (請參閱 lua_Number)。Lua 值必須是數字或可轉換為數字的字串 (請參閱 lua-coercion);否則,lua_tonumber 會返回 0。
lua_topointer lua_topointer()
const void *lua_topointer (lua_State *L, int index);
將指定可接受索引處的值轉換為一般 C 指標 (void*)。該值可以是使用者資料、表格、執行緒或函數;否則,lua_topointer 會返回 NULL。不同的物件會提供不同的指標。沒有辦法將指標轉換回其原始值。
通常,此函數僅用於除錯資訊。
lua_tostring lua_tostring()
const char *lua_tostring (lua_State *L, int index);
等同於 len 等於 NULLlua_tolstring (請參閱 lua_tolstring())。
lua_tothread lua_tothread()
lua_State *lua_tothread (lua_State *L, int index);
將指定可接受索引處的值轉換為 Lua 執行緒 (表示為 lua_State* lua_State)。此值必須為執行緒;否則,該函數會返回 NULL
lua_touserdata lua_touserdata()
void *lua_touserdata (lua_State *L, int index);
如果指定可接受索引處的值是完整使用者資料,則會返回其區塊位址。如果值是輕量使用者資料,則會返回其指標。否則,它會返回 NULL
lua_type lua_type()
int lua_type (lua_State *L, int index);
返回指定可接受索引處的值的類型,對於無效的索引 (也就是指向「空」堆疊位置的索引) 則返回 LUA_TNONElua_type 返回的類型由 lua.h 中定義的以下常數編碼:LUA_TNILLUA_TNUMBERLUA_TBOOLEANLUA_TSTRINGLUA_TTABLELUA_TFUNCTIONLUA_TUSERDATALUA_TTHREADLUA_TLIGHTUSERDATA
lua_typename lua_typename()
const char *lua_typename  (lua_State *L, int tp);
返回由值 tp 編碼的類型名稱,該值必須是 lua_type 返回的值之一。
lua_Writer lua_Writer
typedef int (*lua_Writer) (lua_State *L,
                           const void* p,
                           size_t sz,
                           void* ud);
lua_dump (請參閱 lua_dump()) 使用的寫入器函數。每當它產生另一塊區塊時,lua_dump 會呼叫寫入器,並傳遞要寫入的緩衝區 (p)、其大小 (sz) 和提供給 lua_dumpdata 參數。
寫入器返回錯誤代碼:0 表示沒有錯誤;任何其他值都表示錯誤,並會停止 lua_dump 再次呼叫寫入器。
lua_xmove lua_xmove()
void lua_xmove (lua_State *from, lua_State *to, int n);
相同全域狀態的不同執行緒之間交換值。
此函數會從堆疊 from 中彈出 n 個值,並將它們推送到堆疊 to 上。
lua_yield lua_yield()
int lua_yield (lua_State *L, int nresults);
暫停協程。
此函數應僅作為 C 函數的返回表示式呼叫,如下所示
return lua_yield (L, nresults);
當 C 函數以這種方式呼叫 lua_yield 時,正在執行的協程會暫停執行,並且啟動此協程的 lua_resume (請參閱 lua_resume()) 呼叫會返回。參數 nresults 是從堆疊傳遞為 lua_resume 結果的值數量。
lua-stackexample
作為堆疊操作的範例,如果堆疊開始時為 10 20 30 40 50* (從底部到頂部;* 標記頂部),則
lua_pushvalue(L, 3)    --> 10 20 30 40 50 30*
lua_pushvalue(L, -1)   --> 10 20 30 40 50 30 30*
lua_remove(L, -3)      --> 10 20 30 40 30 30*
lua_remove(L,  6)      --> 10 20 30 40 30*
lua_insert(L,  1)      --> 30 10 20 30 40*
lua_insert(L, -1)      --> 30 10 20 30 40*  (no effect)
lua_replace(L, 2)      --> 30 40 20 30*
lua_settop(L, -3)      --> 30 40*
lua_settop(L,  6)      --> 30 40 nil nil nil nil*

3.8 除錯介面 lua-apiDebug

Lua 沒有內建的除錯工具。相反,它透過函數和鉤子提供了一個特殊的介面。此介面允許建構不同類型的除錯器、效能分析器和其他需要直譯器「內部資訊」的工具。
lua_Debug lua_Debug
typedef struct lua_Debug {
    int event;
    const char *name;           /* (n) */
    const char *namewhat;       /* (n) */
    const char *what;           /* (S) */
    const char *source;         /* (S) */
    int currentline;            /* (l) */
    int nups;                   /* (u) number of upvalues */
    int linedefined;            /* (S) */
    int lastlinedefined;        /* (S) */
    char short_src[LUA_IDSIZE]; /* (S) */
    /* private part */
    other fields
} lua_Debug;
一個結構,用於攜帶有關活動函數的不同資訊片段。lua_getstack (請參閱 lua_getstack()) 僅填入此結構的私人部分,以供稍後使用。若要使用有用的資訊填寫 lua_Debug 的其他欄位,請呼叫 lua_getinfo (請參閱 lua_getinfo())。
lua_Debug 的欄位具有以下含義
source 如果函數是在字串中定義的,則 source 是該字串。如果函數是在檔案中定義的,則 source 會以 @ 開頭,後接檔案名稱。
short_src source 的「可列印」版本,用於錯誤訊息中。
linedefined 函數定義開始所在的行號。
lastlinedefined 函數定義結束所在的行號。
what 如果函數是 Lua 函數,則為字串 "Lua";如果是 C 函數,則為 "C";如果是區塊的主要部分,則為 "main";如果是執行尾部呼叫的函數,則為 "tail"。在後一種情況下,Lua 沒有關於該函數的其他資訊。
currentline 給定函數正在執行的目前行。當沒有可用的行資訊時,currentline 會設定為 -1。
name 給定函式的合理名稱。因為 Lua 中的函式是一等值,它們沒有固定的名稱:有些函式可能是多個全域變數的值,而另一些函式可能只儲存在表格欄位中。lua_getinfo 函式會檢查函式是如何被呼叫的,以找到合適的名稱。如果找不到名稱,則 name 會被設為 NULL
namewhat 解釋 name 欄位。根據函式的呼叫方式,namewhat 的值可以是 "global""local""method""field""upvalue""" (空字串)。(當沒有其他選項適用時,Lua 會使用空字串。) nups 函式的上值數量。
lua_gethook lua_gethook()
lua_Hook lua_gethook (lua_State *L);
返回目前的鉤子函式。
lua_gethookcount lua_gethookcount()
int lua_gethookcount (lua_State *L);
返回目前的鉤子計數。
lua_gethookmask lua_gethookmask()
int lua_gethookmask (lua_State *L);
返回目前的鉤子遮罩。
lua_getinfo lua_getinfo()
int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);
返回有關特定函式或函式呼叫的資訊。
要取得有關函式呼叫的資訊,參數 ar 必須是有效的活動記錄,該記錄是先前呼叫 lua_getstack (請參閱 lua_getstack()) 或作為引數提供給鉤子 (請參閱 lua_Hook) 所填寫的。
要取得有關函式的資訊,您必須將其推入堆疊,並以字元 > 開始 what 字串。(在這種情況下,lua_getinfo 會彈出堆疊頂端的函式。) 例如,要得知函式 f 在哪一行定義的,您可以編寫以下程式碼
lua_Debug ar;
lua_getfield(L, LUA_GLOBALSINDEX, "f");  /* get global 'f' */
lua_getinfo(L, ">S", &ar);
printf("%d\n", ar.linedefined);
字串 what 中的每個字元都會選擇要填寫的結構 ar 的某些欄位,或要推入堆疊的值
'n' 填寫欄位 namenamewhat 'S' 填寫欄位 sourceshort_srclinedefinedlastlinedefinedwhat 'l' 填寫欄位 currentline 'u' 填寫欄位 nups 'f' 將給定層級正在執行的函式推入堆疊 'L' 將一個表格推入堆疊,該表格的索引是函式中有效的行號。(有效行 是具有某些相關程式碼的行,也就是您可以放置中斷點的行。無效行包括空行和註解。)
此函式在發生錯誤時返回 0 (例如,what 中有無效的選項)。
lua_getlocal lua_getlocal()
const char *lua_getlocal (lua_State *L, lua_Debug *ar, int n);
取得有關給定活動記錄的區域變數的資訊。參數 ar 必須是有效的活動記錄,該記錄是先前呼叫 lua_getstack (請參閱 lua_getstack()) 或作為引數提供給鉤子 (請參閱 lua_Hook) 所填寫的。索引 n 會選擇要檢查哪個區域變數 (1 是第一個參數或活動的區域變數,依此類推,直到最後一個活動的區域變數)。lua_getlocal 將變數的值推入堆疊並返回其名稱。
( (左括號) 開頭的變數名稱表示內部變數 (迴圈控制變數、暫時變數和 C 函式區域變數)。
當索引大於活動的區域變數的數量時,返回 NULL (且不推入任何內容)。
lua_getstack lua_getstack()
int lua_getstack (lua_State *L, int level, lua_Debug *ar);
取得有關直譯器執行階段堆疊的資訊。
此函式會使用在給定層級執行的函式的 活動記錄 的識別填寫 lua_Debug (請參閱 lua_Debug) 結構的部分。層級 0 是目前正在執行的函式,而層級 n+1 是呼叫層級 n 的函式。當沒有錯誤時,lua_getstack 會返回 1;當呼叫的層級大於堆疊深度時,則返回 0。
lua_getupvalue lua_getupvalue()
const char *lua_getupvalue (lua_State *L, int funcindex, int n);
取得有關閉包的上值的資訊。(對於 Lua 函式,上值是函式使用的外部區域變數,因此包含在其閉包中。) lua_getupvalue 取得上值的索引 n、將上值的值推入堆疊,並返回其名稱。funcindex 指向堆疊中的閉包。(上值沒有特定的順序,因為它們在整個函式中都是活動的。因此,它們會以任意順序編號。)
當索引大於上值的數量時,返回 NULL (且不推入任何內容)。對於 C 函式,此函式會使用空字串 "" 作為所有上值的名稱。
lua_Hook lua_Hook
typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);
用於除錯鉤子函式的型別。
每當呼叫鉤子時,其 ar 引數的 event 欄位會設定為觸發鉤子的特定事件。Lua 使用以下常數識別這些事件:LUA_HOOKCALLLUA_HOOKRETLUA_HOOKTAILRETLUA_HOOKLINELUA_HOOKCOUNT。此外,對於行事件,也會設定 currentline 欄位。若要取得 ar 中任何其他欄位的值,鉤子必須呼叫 lua_getinfo (請參閱 lua_getinfo())。對於返回事件,event 可以是 LUA_HOOKRET (正常值) 或 LUA_HOOKTAILRET。在後一種情況下,Lua 正在模擬從執行尾呼叫的函式返回;在這種情況下,呼叫 lua_getinfo 是沒有意義的。
當 Lua 正在執行鉤子時,它會停用對鉤子的其他呼叫。因此,如果鉤子回呼 Lua 來執行函式或程式碼區塊,則此執行不會發生任何對鉤子的呼叫。
lua_sethook lua_sethook()
int lua_sethook (lua_State *L, lua_Hook f, int mask, int count);
設定除錯鉤子函式。
引數 f 是鉤子函式。mask 指定將在哪些事件上呼叫鉤子:它由常數 LUA_MASKCALLLUA_MASKRETLUA_MASKLINELUA_MASKCOUNT 的位元邏輯 or 形成。僅當遮罩包含 LUA_MASKCOUNT 時,count 引數才有意義。對於每個事件,都會如下所述呼叫鉤子
呼叫鉤子:在直譯器呼叫函式時呼叫。在 Lua 進入新函式之後、函式取得其引數之前呼叫鉤子。
返回鉤子:在直譯器從函式返回時呼叫。在 Lua 離開函式之前呼叫鉤子。您無法存取函式要返回的值。
行鉤子:在直譯器即將開始執行新的程式碼行,或在程式碼中跳回 (即使跳到同一行) 時呼叫。(此事件僅在 Lua 執行 Lua 函式時發生。)
計數鉤子:在直譯器執行每 count 個指令後呼叫。(此事件僅在 Lua 執行 Lua 函式時發生。)
透過將 mask 設定為零來停用鉤子。
lua_setlocal lua_setlocal()
const char *lua_setlocal (lua_State *L, lua_Debug *ar, int n);
設定給定活動記錄的區域變數的值。參數 arnlua_getlocal 中的相同 (請參閱 lua_getlocal())。lua_setlocal 將堆疊頂部的值指派給變數,並返回其名稱。它也會從堆疊中彈出值。
當索引大於活動的區域變數的數量時,返回 NULL (且不彈出任何內容)。
lua_setupvalue lua_setupvalue()
const char *lua_setupvalue (lua_State *L, int funcindex, int n);
設定閉包的上值的值。它將堆疊頂部的值指派給上值,並返回其名稱。它也會從堆疊中彈出值。參數 funcindexnlua_getupvalue 中的相同 (請參閱 lua_getupvalue())。
當索引大於上值的數量時,返回 NULL (且不彈出任何內容)。
lua-debugexample
例如,以下函式會列出堆疊中給定層級的函式的所有區域變數和上值的名稱
int listvars (lua_State *L, int level) {
  lua_Debug ar;
  int i;
  const char *name;
  if (lua_getstack(L, level, &ar) == 0)
    return 0;  /* failure: no such level in the stack */
  i = 1;
  while ((name = lua_getlocal(L, &ar, i++)) != NULL) {
    printf("local %d %s\n", i-1, name);
    lua_pop(L, 1);  /* remove variable value */
  }
  lua_getinfo(L, "f", &ar);  /* retrieves function */
  i = 1;
  while ((name = lua_getupvalue(L, -1, i++)) != NULL) {
    printf("upvalue %d %s\n", i-1, name);
    lua_pop(L, 1);  /* remove upvalue value */
  }
  return 1;
}

4 輔助函式庫 lua-aux

輔助函式庫提供了幾個方便的函式,可讓 C 與 Lua 介面。雖然基本 API 提供了 C 與 Lua 之間所有互動的基本函式,但輔助函式庫為某些常見任務提供了更進階的函式。
輔助函式庫的所有函式都在標頭檔 lauxlib.h 中定義,並具有前置詞 luaL_
輔助函式庫中的所有函式都建構在基本 API 之上,因此它們不提供任何無法使用此 API 完成的功能。
輔助函式庫中的幾個函式用於檢查 C 函式引數。它們的名稱始終為 luaL_check*luaL_opt*。如果檢查不符合條件,所有這些函式都會引發錯誤。由於錯誤訊息是針對引數格式化的 (例如,「錯誤引數 #1」),因此您不應將這些函式用於其他堆疊值。

4.1 函式和型別 lua-auxFunctions

在這裡,我們以字母順序列出輔助函式庫中的所有函式和型別。
luaL_addchar luaL_addchar()
void luaL_addchar (luaL_Buffer *B, char c);
將字元 c 新增至緩衝區 B (請參閱 luaL_Buffer)。
luaL_addlstring luaL_addlstring()
void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l);
s 所指向的長度為 l 的字串新增至緩衝區 B (請參閱 luaL_Buffer)。該字串可能包含內嵌的零。
luaL_addsize luaL_addsize()
void luaL_addsize (luaL_Buffer *B, size_t n);
將長度為 n 的字串新增至緩衝區 B (請參閱 luaL_Buffer),該字串先前已複製到緩衝區區域 (請參閱 luaL_prepbuffer())。
luaL_addstring luaL_addstring()
void luaL_addstring (luaL_Buffer *B, const char *s);
s 指向的以零結尾的字串加入緩衝區 B (請參閱 luaL_Buffer)。該字串不得包含內嵌的零。
luaL_addvalue luaL_addvalue()
void luaL_addvalue (luaL_Buffer *B);
將堆疊頂端的值加入緩衝區 B (請參閱 luaL_Buffer)。並將該值從堆疊中彈出。
這是字串緩衝區上唯一可以(而且必須)在堆疊上帶有一個額外元素呼叫的函式,該元素是要加入緩衝區的值。
luaL_argcheck luaL_argcheck()
void luaL_argcheck (lua_State *L,
                    int cond,
                    int narg,
                    const char *extramsg);
檢查 cond 是否為真。若否,則會引發錯誤,錯誤訊息如下,其中 func 是從呼叫堆疊中取得的
bad argument #<narg> to <func> (<extramsg>)
luaL_argerror luaL_argerror()
int luaL_argerror (lua_State *L, int narg, const char *extramsg);
引發錯誤,錯誤訊息如下,其中 func 是從呼叫堆疊中取得的
bad argument #<narg> to <func> (<extramsg>)
此函式永遠不會返回,但在 C 函式中通常會使用它,如 return luaL_argerror( args )
luaL_Buffer luaL_Buffer
typedef struct luaL_Buffer luaL_Buffer;
字串緩衝區的類型。
字串緩衝區允許 C 程式碼以片段方式建構 Lua 字串。其使用模式如下
首先,您要宣告一個 luaL_Buffer 類型的變數 b
然後使用呼叫 luaL_buffinit(L, &b) 初始化它 (請參閱 luaL_buffinit())。
然後呼叫任何 luaL_add* 函式,將字串片段加入緩衝區。
最後呼叫 luaL_pushresult(&b) (請參閱 luaL_pushresult())。此呼叫會將最終字串留在堆疊頂端。
在其正常運作期間,字串緩衝區會使用可變數量的堆疊位置。因此,在使用緩衝區時,您不能假設您知道堆疊頂端的位置。只要該使用是平衡的,您就可以在連續的緩衝區操作之間使用堆疊;也就是說,當您呼叫緩衝區操作時,堆疊處於與前一個緩衝區操作後立即相同的層級。(此規則的唯一例外是 luaL_addvalue luaL_addvalue()。) 呼叫 luaL_pushresult 後,堆疊會回到緩衝區初始化時的層級,再加上頂端的最終字串。
luaL_buffinit luaL_buffinit()
void luaL_buffinit (lua_State *L, luaL_Buffer *B);
初始化緩衝區 B。此函式不配置任何空間;緩衝區必須宣告為變數 (請參閱 luaL_Buffer)。
luaL_callmeta luaL_callmeta()
int luaL_callmeta (lua_State *L, int obj, const char *e);
呼叫元方法。
如果索引 obj 的物件具有元表,且此元表具有欄位 e,則此函式會呼叫此欄位,並將物件作為其唯一引數傳遞。在此情況下,此函式會返回 1,並將呼叫返回的值推入堆疊。如果沒有元表或沒有元方法,則此函式會返回 0 (而不在堆疊上推入任何值)。
luaL_checkany luaL_checkany()
void luaL_checkany (lua_State *L, int narg);
檢查函式在位置 narg 是否具有任何類型的引數 (包括 nil)。
luaL_checkint luaL_checkint()
int luaL_checkint (lua_State *L, int narg);
檢查函式引數 narg 是否為數字,並返回此數字轉換為 int 的結果。
luaL_checkinteger luaL_checkinteger()
lua_Integer luaL_checkinteger (lua_State *L, int narg);
檢查函式引數 narg 是否為數字,並返回此數字轉換為 lua_Integer 的結果 (請參閱 lua_Integer)。
luaL_checklong luaL_checklong()
long luaL_checklong (lua_State *L, int narg);
檢查函式引數 narg 是否為數字,並返回此數字轉換為 long 的結果。
luaL_checklstring luaL_checklstring()
const char *luaL_checklstring (lua_State *L, int narg, size_t *l);
檢查函式引數 narg 是否為字串,並返回此字串;如果 l 不是 NULL,則以字串的長度填入 *l
luaL_checknumber luaL_checknumber()
lua_Number luaL_checknumber (lua_State *L, int narg);
檢查函式引數 narg 是否為數字,並返回此數字 (請參閱 lua_Number)。
luaL_checkoption luaL_checkoption()
int luaL_checkoption (lua_State *L,
                      int narg,
                      const char *def,
                      const char *const lst[]);
檢查函式引數 narg 是否為字串,並在陣列 lst 中搜尋此字串 (該陣列必須以 NULL 結尾)。返回在陣列中找到字串的索引。如果引數不是字串或找不到字串,則會引發錯誤。
如果 def 不是 NULL,則當沒有引數 narg 或此引數為 nil 時,函式會使用 def 作為預設值。
這是將字串對應到 C 列舉的實用函式。(Lua 程式庫中的慣例通常是使用字串而不是數字來選取選項。)
luaL_checkstack luaL_checkstack()
void luaL_checkstack (lua_State *L, int sz, const char *msg);
將堆疊大小擴展為 top + sz 個元素,如果堆疊無法擴展到該大小,則會引發錯誤。msg 是要加入錯誤訊息中的額外文字。
luaL_checkstring luaL_checkstring()
const char *luaL_checkstring (lua_State *L, int narg);
檢查函式引數 narg 是否為字串,並返回此字串。
luaL_checktype luaL_checktype()
void luaL_checktype (lua_State *L, int narg, int t);
檢查函式引數 narg 是否具有類型 t (請參閱 lua_type())。
luaL_checkudata luaL_checkudata()
void *luaL_checkudata (lua_State *L, int narg, const char *tname);
檢查函式引數 narg 是否為類型 tname 的 userdata (請參閱 luaL_newmetatable())。
luaL_dofile luaL_dofile()
int luaL_dofile (lua_State *L, const char *filename);
載入並執行給定的檔案。它被定義為以下巨集
(luaL_loadfile(L, filename) || lua_pcall(L, 0, LUA_MULTRET, 0))
如果沒有錯誤則返回 0,如果發生錯誤則返回 1。
luaL_dostring luaL_dostring()
int luaL_dostring (lua_State *L, const char *str);
載入並執行給定的字串。它被定義為以下巨集
(luaL_loadstring(L, str) || lua_pcall(L, 0, LUA_MULTRET, 0))
如果沒有錯誤則返回 0,如果發生錯誤則返回 1。
luaL_error luaL_error()
int luaL_error (lua_State *L, const char *fmt, ...);
引發錯誤。錯誤訊息格式由 fmt 加上任何額外引數給定,遵循與 lua_pushfstring 相同的規則 (請參閱 lua_pushfstring())。如果此資訊可用,它也會在訊息開頭加入發生錯誤的檔案名稱和行號。
此函式永遠不會返回,但在 C 函式中通常會使用它,如 return luaL_error( args )
luaL_getmetafield luaL_getmetafield()
int luaL_getmetafield (lua_State *L, int obj, const char *e);
將索引 obj 的物件的元表中的欄位 e 推入堆疊。如果物件沒有元表,或者元表沒有此欄位,則會返回 0 且不推入任何內容。
luaL_getmetatable luaL_getmetatable()
void luaL_getmetatable (lua_State *L, const char *tname);
將與登錄表中的名稱 tname 相關聯的元表推入堆疊 (請參閱 luaL_newmetatable())。
luaL_gsub luaL_gsub()
const char *luaL_gsub (lua_State *L,
                       const char *s,
                       const char *p,
                       const char *r);
建立字串 s 的副本,方法是將字串 p 的任何出現次數取代為字串 r。將結果字串推入堆疊並返回它。
luaL_loadbuffer luaL_loadbuffer()
int luaL_loadbuffer (lua_State *L,
                     const char *buff,
                     size_t sz,
                     const char *name);
將緩衝區載入為 Lua 區塊。此函式使用 lua_load (請參閱 lua_load()) 來載入 buff 指向的緩衝區中,大小為 sz 的區塊。
此函式返回與 lua_load 相同的結果。name 是區塊名稱,用於除錯資訊和錯誤訊息。
luaL_loadfile luaL_loadfile()
int luaL_loadfile (lua_State *L, const char *filename);
將檔案載入為 Lua 區塊。此函式使用 lua_load (請參閱 lua_load()) 來載入名為 filename 的檔案中的區塊。如果 filenameNULL,則從標準輸入載入。如果檔案中的第一行以 # 開頭,則會忽略該行。
此函式返回與 lua_load 相同的結果,但如果無法開啟/讀取檔案,則會有額外的錯誤碼 LUA_ERRFILE
lua_load 一樣,此函式只載入區塊;它不會執行區塊。
luaL_loadstring luaL_loadstring()
int luaL_loadstring (lua_State *L, const char *s);
將字串載入為 Lua 區塊。此函式使用 lua_load (請參閱 lua_load()) 來載入以零結尾的字串 s 中的區塊。
此函式返回與 lua_load 相同的結果。
也與 lua_load 一樣,此函式只載入區塊;它不會執行區塊。
luaL_newmetatable luaL_newmetatable()
int luaL_newmetatable (lua_State *L, const char *tname);
如果登錄表已經具有索引鍵 tname,則返回 0。否則,會建立一個新的表格以用作 userdata 的元表,並將其以索引鍵 tname 加入登錄表,並返回 1。
在這兩種情況下,都會將與登錄表中的 tname 相關聯的最終值推入堆疊。
luaL_newstate luaL_newstate()
lua_State *luaL_newstate (void);
建立新的 Lua 狀態。它會使用基於標準 C realloc 函式的配置器呼叫 lua_newstate (請參閱 lua_newstate()),然後設定一個 panic 函式 (請參閱 lua_atpanic()),以便在發生嚴重錯誤時將錯誤訊息列印到標準錯誤輸出。
返回新狀態,如果發生記憶體配置錯誤,則返回 NULL
luaL_openlibs luaL_openlibs()
void luaL_openlibs (lua_State *L);
將所有標準 Lua 程式庫開啟到給定的狀態。另請參閱 lua-openlibs 以取得有關如何開啟個別程式庫的詳細資訊。
luaL_optint luaL_optint()
int luaL_optint (lua_State *L, int narg, int d);
如果函式引數 narg 為數字,則返回此數字轉換為 int 的結果。如果此引數不存在或為 nil,則返回 d。否則,會引發錯誤。
luaL_optinteger luaL_optinteger()
lua_Integer luaL_optinteger (lua_State *L,
                             int narg,
                             lua_Integer d);
如果函數參數 narg 是一個數字,則會回傳轉換為 lua_Integer (參見 lua_Integer) 的該數字。如果此參數不存在或為 nil,則會回傳 d。否則,會引發錯誤。
luaL_optlong luaL_optlong()
long luaL_optlong (lua_State *L, int narg, long d);
如果函數參數 narg 是一個數字,則會回傳轉換為 long 的該數字。如果此參數不存在或為 nil,則會回傳 d。否則,會引發錯誤。
luaL_optlstring luaL_optlstring()
const char *luaL_optlstring (lua_State *L,
                             int narg,
                             const char *d,
                             size_t *l);
如果函數參數 narg 是一個字串,則會回傳此字串。如果此參數不存在或為 nil,則會回傳 d。否則,會引發錯誤。
如果 l 不是 NULL,則會將結果的長度填入 *l 的位置。
luaL_optnumber luaL_optnumber()
lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number d);
如果函數參數 narg 是一個數字,則會回傳此數字。如果此參數不存在或為 nil,則會回傳 d。否則,會引發錯誤。
luaL_optstring luaL_optstring()
const char *luaL_optstring (lua_State *L,
                            int narg,
                            const char *d);
如果函數參數 narg 是一個字串,則會回傳此字串。如果此參數不存在或為 nil,則會回傳 d。否則,會引發錯誤。
luaL_prepbuffer luaL_prepbuffer()
char *luaL_prepbuffer (luaL_Buffer *B);
回傳一個大小為 LUAL_BUFFERSIZE 的空間位址,您可以在此複製要新增到緩衝區 B 的字串 (參見 luaL_Buffer)。將字串複製到此空間後,您必須呼叫 luaL_addsize (參見 luaL_addsize()) 並傳入字串的大小,才能實際將字串新增到緩衝區。
luaL_pushresult luaL_pushresult()
void luaL_pushresult (luaL_Buffer *B);
完成緩衝區 B 的使用,並將最終字串留在堆疊頂端。
luaL_ref luaL_ref()
int luaL_ref (lua_State *L, int t);
在索引為 t 的表格中,為堆疊頂端的物件建立並回傳一個 reference (並將該物件彈出堆疊)。
參考是一個唯一的整數索引鍵。只要您不手動將整數索引鍵新增到表格 t 中,luaL_ref 就會確保其回傳的索引鍵的唯一性。您可以透過呼叫 lua_rawgeti(L, t, r) (參見 lua_rawgeti()) 來擷取參考 r 所指的物件。函式 luaL_unref (參見 luaL_unref()) 會釋放參考及其相關聯的物件。
如果堆疊頂端的物件為 nil,則 luaL_ref 會回傳常數 LUA_REFNIL。常數 LUA_NOREF 保證與 luaL_ref 回傳的任何參考都不同。
luaL_Reg luaL_Reg
typedef struct luaL_Reg {
    const char *name;
    lua_CFunction func;
} luaL_Reg;
用於 luaL_register (參見 luaL_register()) 註冊的函數陣列的類型。name 是函數名稱,而 func 是指向該函數的指標。任何 luaL_Reg 陣列都必須以哨兵條目結尾,其中 namefunc 均為 NULL
luaL_register luaL_register()
void luaL_register (lua_State *L,
                    const char *libname,
                    const luaL_Reg *l);
開啟一個程式庫。
當以 libname 等於 NULL 呼叫時,它只會將列表 l (參見 luaL_Reg) 中的所有函數註冊到堆疊頂端的表格中。
當以非 null 的 libname 呼叫時,luaL_register 會建立一個新的表格 t,將其設定為全域變數 libname 的值,將其設定為 package.loaded[libname] 的值,並將列表 l 中的所有函數註冊到其中。如果 package.loaded[libname] 或變數 libname 中有表格,則會重複使用此表格,而不是建立新的表格。
在任何情況下,此函式都會將表格留在堆疊頂端。
luaL_typename luaL_typename()
const char *luaL_typename (lua_State *L, int idx);
回傳索引 idx 處的值的類型名稱。
luaL_typerror luaL_typerror()
int luaL_typerror (lua_State *L, int narg, const char *tname);
產生錯誤訊息,如下所示:
location : 不良參數 narg 'func' ( tname 預期,得到 rt )
其中 locationluaL_where (參見 luaL_where()) 產生,func 是目前函數的名稱,而 rt 是實際參數的類型名稱。
luaL_unref luaL_unref()
void luaL_unref (lua_State *L, int t, int ref);
從索引為 t 的表格中釋放參考 ref (參見 luaL_ref())。該條目會從表格中移除,以便可以收集所參考的物件。參考 ref 也會被釋放,以便再次使用。
如果 refLUA_NOREFLUA_REFNIL,則 luaL_unref 不會執行任何動作。
luaL_where luaL_where()
void luaL_where (lua_State *L, int lvl);
將一個字串推送到堆疊中,該字串會識別呼叫堆疊中層級 lvl 處的控制項目前位置。此字串通常具有下列格式:
chunkname:currentline
層級 0 是正在執行的函數,層級 1 是呼叫正在執行函數的函數,依此類推。
此函數用於建立錯誤訊息的前綴。

5 標準程式庫 lua-lib

標準程式庫提供透過 C API 直接實作的實用函數。其中一些函數為該語言提供基本服務 (例如,typegetmetatable);其他函數提供對「外部」服務的存取權 (例如,I/O);而其他函數則可以在 Lua 本身中實作,但相當實用或具有關鍵的效能需求,因此值得在 C 中實作 (例如,sort)。
所有程式庫都是透過官方 C API 實作,並以個別 C 模組的形式提供。目前,Lua 具有下列標準程式庫:
基本程式庫;
套件程式庫;
字串操作;
表格操作;
數學函數 (sin、log 等);
輸入和輸出;
作業系統設施;
偵錯設施。
除了基本程式庫和套件程式庫之外,每個程式庫都會將其所有函數作為全域表格的欄位或其物件的方法提供。
lua-openlibs
若要存取這些程式庫,C 主機程式應呼叫 luaL_openlibs 函數,以開啟所有標準程式庫 (參見 luaL_openlibs())。或者,主機程式可以個別開啟程式庫,方法是呼叫 luaopen_base (用於基本程式庫)、luaopen_package (用於套件程式庫)、luaopen_string (用於字串程式庫)、luaopen_table (用於表格程式庫)、luaopen_math (用於數學程式庫)、luaopen_io (用於 I/O 和作業系統程式庫) 和 luaopen_debug (用於偵錯程式庫)。這些函數在 lualib.h 中宣告,且不應直接呼叫:您必須像任何其他 Lua C 函數一樣呼叫它們,例如,透過使用 lua_call (參見 lua_call())。

5.1 基本函數 lua-lib-core

基本程式庫提供 Lua 的一些核心函數。如果您的應用程式中不包含此程式庫,您應仔細檢查是否需要為其某些功能提供實作。
assert({v} [, {message}]) assert()
當其參數 v 的值為 false (即 nilfalse) 時,會發出錯誤訊息;否則,會回傳其所有參數。message 是錯誤訊息;如果不存在,則預設為「assertion failed!」。
collectgarbage({opt} [, {arg}]) collectgarbage()
此函數是垃圾收集器的通用介面。它會根據其第一個參數 {opt} 執行不同的函數:
"stop" 停止垃圾收集器。"restart" 重新啟動垃圾收集器。"collect" 執行完整的垃圾收集週期。"count" 回傳 Lua 使用的總記憶體 (以 Kbytes 為單位)。"step" 執行垃圾收集步驟。步驟「大小」由 {arg} 控制 (較大的值表示更多步驟),但方式未指定。如果您想要控制步驟大小,則必須以實驗方式調整 {arg} 的值。如果步驟完成收集週期,則會回傳 true"setpause"{arg} /100 設定為收集器 pause 的新值 (參見 lua-gc)。"setstepmul"{arg} /100 設定為收集器 `step multiplier` 的新值 (參見 lua-gc)。
dofile({filename}) dofile()
開啟指定的檔案,並將其內容當做 Lua 程式碼區塊執行。當呼叫時不帶參數,dofile 會執行標準輸入 (stdin) 的內容。回傳程式碼區塊回傳的所有值。如果發生錯誤,dofile 會將錯誤傳播到其呼叫者 (亦即,dofile 不會在受保護模式下執行)。
error({message} [, {level}]) error()
終止最後一個受保護的呼叫函式,並回傳 message 作為錯誤訊息。函式 {error} 永遠不會回傳。
通常,{error} 會在訊息開頭新增一些關於錯誤位置的資訊。{level} 參數會指定如何取得錯誤位置。使用層級 1 (預設值),錯誤位置是呼叫 {error} 函數的位置。層級 2 會將錯誤指向呼叫 {error} 的函數的呼叫位置;依此類推。傳遞層級 0 可避免將錯誤位置資訊新增到訊息中。
_G _G
一個全域變數 (不是函式),它會保留全域環境 (即 _G._G = _G)。Lua 本身不使用此變數;變更其值不會影響任何環境,反之亦然。(使用 setfenv 變更環境。)
getfenv({f}) getfenv()
回傳函數正在使用的目前環境。{f} 可以是 Lua 函數或指定該堆疊層級函數的數字:層級 1 是呼叫 getfenv 的函數。如果給定的函數不是 Lua 函數,或者如果 {f} 為 0,則 getfenv 會回傳全域環境。{f} 的預設值為 1。
getmetatable({object}) getmetatable()
如果 {object} 沒有元表,則會回傳 nil。否則,如果物件的元表具有 "__metatable" 欄位,則會回傳相關聯的值。否則,會回傳給定物件的元表。
ipairs({t}) ipairs()
回傳三個值:一個 iterator 函數、表格 {t} 和 0,以便建構
for i,v in ipairs(t) do body end
會迭代遍歷鍵值對 (1,t[1]), (2,t[2]), ..., 直到表格中第一個不存在的整數鍵。
load({func} [, {chunkname}]) load()
使用函式 {func} 來載入程式碼區塊,以取得其片段。每次呼叫 {func} 都必須回傳一個字串,並與先前的結果串接。回傳 nil(或沒有值)表示程式碼區塊的結束。
如果沒有錯誤,則回傳已編譯的程式碼區塊作為函式;否則,回傳 nil 加上錯誤訊息。回傳函式的環境為全域環境。
{chunkname} 用於錯誤訊息和偵錯資訊中的程式碼區塊名稱。
loadfile([{filename}]) loadfile()
類似於 load (參見 load()),但從檔案 {filename} 或標準輸入取得程式碼區塊,如果沒有給定檔案名稱的話。
loadstring({string} [, {chunkname}]) loadstring()
類似於 load (參見 load()),但從給定的 {string} 取得程式碼區塊。
要載入並執行給定的字串,請使用以下慣用語
assert(loadstring(s))()
next({table} [, {index}]) next()
允許程式遍歷表格的所有欄位。它的第一個參數是一個表格,而第二個參數是該表格中的索引。next 會回傳表格的下一個索引及其關聯的值。當以 nil 作為第二個參數呼叫時,next 會回傳初始索引及其關聯的值。當以最後一個索引呼叫,或在空表格中以 nil 呼叫時,next 會回傳 nil。如果第二個參數不存在,則會將其解讀為 nil。特別地,您可以使用 next(t) 來檢查表格是否為空。
列舉索引的順序未指定,即使是數字索引也是如此。(若要依數字順序遍歷表格,請使用數值 foripairs() 函式。)
如果在遍歷期間,您將任何值指派給表格中不存在的欄位,則 next 的行為是未定義的。但是,您可以修改現有的欄位。特別是,您可以清除現有的欄位。
pairs({t}) pairs()
回傳三個值:next() 函式、表格 {t}nil,以便建構
for k,v in pairs(t) do body end
將會迭代遍歷表格 {t} 的所有鍵值對。
pcall({f}, {arg1}, {...}) pcall()
保護模式使用給定的引數呼叫函式 {f}。這表示 {f} 內部的任何錯誤都不會傳播;相反地,pcall 會捕獲錯誤並回傳狀態碼。它的第一個結果是狀態碼 (布林值),如果呼叫成功且沒有錯誤,則為 true。在這種情況下,pcall 也會在此第一個結果之後,回傳所有來自呼叫的結果。如果發生任何錯誤,pcall 會回傳 false 加上錯誤訊息。
print({...}) print()
接收任意數量的引數,並使用 tostring tostring() 函式將其轉換為字串,然後將其值列印到 stdoutprint 不適用於格式化輸出,而僅適用於快速顯示數值,通常用於除錯。如需格式化輸出,請使用 string.format (參見 string.format())。
rawequal({v1}, {v2}) rawequal()
檢查 {v1} 是否等於 {v2},而不呼叫任何元方法。回傳一個布林值。
rawget({table}, {index}) rawget()
取得 table[index] 的實際值,而不呼叫任何元方法。{table} 必須是表格;{index} 可以是任何值。
rawset({table}, {index}, {value}) rawset()
table[index] 的實際值設定為 {value},而不呼叫任何元方法。{table} 必須是表格,{index} 可以是任何不是 nil 的值,而 {value} 可以是任何 Lua 值。
此函式回傳 {table}
select({index}, {...}) select()
如果 {index} 是數字,則回傳引數編號 {index} 之後的所有引數。否則,{index} 必須是字串 "#",而 select 會回傳它接收到的額外引數總數。
setfenv({f}, {table}) setfenv()
設定給定函式要使用的環境。{f} 可以是 Lua 函式或指定該堆疊層級函式的數字:層級 1 是呼叫 setfenv 的函式。setfenv 回傳給定的函式。
作為特例,當 {f} 為 0 時,setfenv 會變更執行緒的環境。在這種情況下,setfenv 不回傳任何值。
setmetatable({table}, {metatable}) setmetatable()
設定給定表格的元表格。(您無法從 Lua 變更其他類型的元表格,只能從 C 變更。) 如果 {metatable}nil,則會移除給定表格的元表格。如果原始的元表格具有 "__metatable" 欄位,則會引發錯誤。
此函式回傳 {table}
tonumber({e} [, {base}]) tonumber()
嘗試將其引數轉換為數字。如果引數已經是數字或可轉換為數字的字串,則 tonumber 會回傳此數字;否則,它會回傳 nil
可選的引數指定解釋數字的進位制。進位制可以是 2 到 36 之間的任何整數 (包含 2 和 36)。在 10 以上的進位制中,字母 A (不論大小寫) 代表 10,B 代表 11,依此類推,Z' 代表 35。在 10 進位 (預設值) 中,數字可以有小數部分,以及可選的指數部分 (參見 lua-lexical)。在其他進位制中,僅接受無正負號的整數。
tostring({e}) tostring()
接收任何類型的引數,並以合理的格式將其轉換為字串。若要完全控制數字的轉換方式,請使用 string.format (參見 string.format())。
__tostring
如果 {e} 的元表格具有 "__tostring" 欄位,則 tostring 會以 {e} 作為引數呼叫對應的值,並使用呼叫的結果作為其結果。
type({v}) lua-type()
回傳其唯一引數的類型,並將其編碼為字串。此函式的可能結果為 "nil" (字串,而非值 nil)、"number""string""boolean"table""function""thread""userdata"
unpack({list} [, {i} [, {j}]]) unpack()
從給定的表格回傳元素。此函式等同於
return list[i], list[i+1], ..., list[j]
除了上面的程式碼只能針對固定數量的元素撰寫之外。預設情況下,{i} 為 1,而 {j} 是由長度運算子所定義的列表長度 (參見 lua-length)。
_VERSION _VERSION
一個全域變數 (非函式),其中包含一個字串,該字串包含目前的直譯器版本。此字串的目前內容為 "Lua 5.1"
xpcall({f}, {err}) xpcall()
此函式類似於 pcall (參見 pcall()),但您可以設定新的錯誤處理常式。
xpcall 以保護模式呼叫函式 {f},並使用 {err} 作為錯誤處理常式。{f} 內部的任何錯誤都不會傳播;相反地,xpcall 會捕獲錯誤,以原始的錯誤物件呼叫 {err} 函式,並回傳狀態碼。它的第一個結果是狀態碼 (布林值),如果呼叫成功且沒有錯誤,則為 true。在這種情況下,xpcall 也會在此第一個結果之後,回傳所有來自呼叫的結果。如果發生任何錯誤,xpcall 會回傳 false 加上來自 {err} 的結果。

5.2 協同程式操作 lua-lib-coroutine

與協同程式相關的操作包含基本函式庫的子函式庫,並位於表格 coroutine 內。如需協同程式的一般說明,請參見 lua-coroutine
coroutine.create({f}) coroutine.create()
建立一個新的協同程式,其主體為 {f}{f} 必須是 Lua 函式。回傳這個新的協同程式,一個類型為 "thread" 的物件。
coroutine.resume({co} [, {val1}, {...}]) coroutine.resume()
開始或繼續執行協同程式 {co}。第一次恢復協同程式時,它會開始執行其主體。值 {val1}, {...} 會作為引數傳遞給主體函式。如果協同程式已暫停,resume 會重新啟動它;值 {val1}, {...} 會作為 yield 的結果傳遞。
如果協同程式在沒有任何錯誤的情況下執行,resume 會回傳 true 加上傳遞給 yield 的任何值 (如果協同程式暫停) 或主體函式回傳的任何值 (如果協同程式終止)。如果發生任何錯誤,resume 會回傳 false 加上錯誤訊息。
coroutine.running() coroutine.running()
回傳正在執行的協同程式,或在主執行緒呼叫時回傳 nil
coroutine.status({co}) coroutine.status()
以字串形式返回協程 {co} 的狀態:如果協程正在運行(即,它呼叫了 status),則返回 "running";如果協程在呼叫 yield 時暫停,或者尚未開始運行,則返回 "suspended";如果協程處於活動狀態但未運行(即,它已恢復另一個協程),則返回 "normal";如果協程已完成其主體函數,或因錯誤而停止,則返回 "dead"
coroutine.wrap({f}) coroutine.wrap()
創建一個新的協程,其主體為 {f}{f} 必須是一個 Lua 函數。返回一個函數,該函數每次被呼叫時都會恢復協程。傳遞給該函數的任何參數都如同傳遞給 resume 的額外參數。返回與 resume 返回的相同的值,除了第一個布林值。如果發生錯誤,則會傳播該錯誤。
coroutine.yield({...}) coroutine.yield()
暫停呼叫協程的執行。協程不能正在運行 C 函數、元方法或 迭代器。傳遞給 yield 的任何參數都會作為額外結果傳遞給 resume

5.3 模組 lua-modules

package 庫提供了在 Lua 中載入和建構模組的基本工具。它直接在全域環境中匯出其兩個函數:requiremodule(請參閱 require()module())。其他所有內容都在表格 package 中匯出。
module({name} [, {...}]) module()
創建一個模組。如果 package.loaded[name] 中有一個表格,則此表格就是模組。否則,如果存在一個具有給定名稱的全域表格 t,則此表格就是模組。否則,創建一個新的表格 t 並將其設定為全域 {name} 的值和 package.loaded[name] 的值。此函數還使用給定的名稱初始化 t._NAME,使用模組(t 本身)初始化 t._M,並使用封裝名稱(完整模組名稱減去最後一個元件;請參閱下文)初始化 t._PACKAGE。最後,modulet 設定為目前函數的新環境和 package.loaded[name] 的新值,以便 require() 返回 t
如果 {name} 是一個複合名稱(即,元件以點號分隔),則 module 會為每個元件創建(或重複使用,如果它們已存在)表格。例如,如果 {name}a.b.c,則 module 將模組表格儲存在全域 a 的欄位 b 的欄位 c 中。
此函數可以在模組名稱後接收可選的 options,其中每個選項都是一個要應用於模組的函數。
require({modname}) require()
載入給定的模組。該函數首先查看 package.loaded 表格,以確定 {modname} 是否已載入。如果是,則 require 返回儲存在 package.loaded[modname] 中的值。否則,它會嘗試尋找模組的 loader
要尋找載入器,首先 require 查詢 package.preload[modname]。如果它有值,則此值(應該是一個函數)就是載入器。否則,require 會使用儲存在 package.path 中的路徑搜尋 Lua 載入器。如果也失敗了,它會使用儲存在 package.cpath 中的路徑搜尋 C 載入器。如果也失敗了,它會嘗試使用 all-in-one 載入器(請參閱下文)。
在載入 C 函式庫時,require 首先使用動態連結工具將應用程式與函式庫連結。然後,它會嘗試在此函式庫中尋找一個 C 函數以用作載入器。此 C 函數的名稱是字串 "luaopen_",串聯上模組名稱的副本,其中每個點號都替換為底線。此外,如果模組名稱有連字號,則會移除其直到(包括)第一個連字號的前綴。例如,如果模組名稱是 a.v1-b.c,則函數名稱將為 luaopen_b_c
如果 require 找不到模組的 Lua 函式庫或 C 函式庫,它會呼叫 all-in-one loader。此載入器會搜尋 C 路徑以尋找給定模組的根名稱的函式庫。例如,當要求 a.b.c 時,它會搜尋 a 的 C 函式庫。如果找到,它會在其中尋找子模組的開啟函數;在我們的範例中,那將是 luaopen_a_b_c。透過此工具,套件可以將多個 C 子模組封裝到一個函式庫中,每個子模組都保留其原始開啟函數。
找到載入器後,require 會使用單一引數 {modname} 呼叫載入器。如果載入器傳回任何值,則 require 會將傳回的值指派給 package.loaded[modname]。如果載入器沒有傳回任何值,並且沒有將任何值指派給 package.loaded[modname],則 require 會將 true 指派給此項目。無論如何,require 都會傳回 package.loaded[modname] 的最終值。
如果在載入或運行模組時發生任何錯誤,或者它找不到模組的任何載入器,則 require 會發出錯誤訊號。
package.cpath package.cpath
require 用於搜尋 C 載入器的路徑。
Lua 使用環境變數 LUA_CPATH(加上 luaconf.h 中定義的另一個預設路徑)以與初始化 Lua 路徑 package.path 相同的方式初始化 C 路徑 package.cpath
package.loaded package.loaded()
require 用於控制已載入哪些模組的表格。當您要求模組 modnamepackage.loaded[modname] 不為 false 時,require 只會傳回儲存在該處的值。
package.loadlib({libname}, {funcname}) package.loadlib()
將主機程式與 C 函式庫 {libname} 動態連結。在此函式庫中,尋找函數 {funcname} 並將此函數作為 C 函數傳回。(因此,{funcname} 必須遵循協定(請參閱 lua_CFunction))。
這是一個低階函數。它完全繞過封裝和模組系統。與 require 不同,它不會執行任何路徑搜尋,也不會自動新增擴充功能。{libname} 必須是 C 函式庫的完整檔案名稱,包括必要時的路徑和擴充功能。{funcname} 必須是 C 函式庫匯出的確切名稱(可能取決於使用的 C 編譯器和連結器)。
ANSI C 不支援此函數。因此,它僅在某些平台上可用(Windows、Linux、Mac OS X、Solaris、BSD 以及其他支援 dlfcn 標準的 Unix 系統)。
package.path package.path
require 用於搜尋 Lua 載入器的路徑。
在啟動時,如果未定義環境變數,則 Lua 使用環境變數 LUA_PATH 的值或 luaconf.h 中定義的預設路徑來初始化此變數。環境變數值中的任何 ";;" 都會被預設路徑取代。
路徑是分號分隔的 templates 序列。對於每個範本,require 會將範本中的每個問號變更為 filename,它是 modname,其中每個點號都替換為「目錄分隔符號」(例如 Unix 中的 "/");然後,它會嘗試載入產生的檔案名稱。因此,例如,如果 Lua 路徑是
"./?.lua;./?.lc;/usr/local/?/init.lua"
則對模組 foo 的 Lua 載入器搜尋將嘗試按該順序載入檔案 ./foo.lua./foo.lc/usr/local/foo/init.lua
package.preload package.preload()
用於儲存特定模組的載入器的表格(請參閱 require())。
package.seeall({module}) package.seeall()
使用其 __index 欄位參照全域環境,為 {module} 設定一個元表格,以便此模組繼承全域環境中的值。用作函數 {module} 的選項。

5.4 字串操作 lua-lib-string

此函式庫提供用於字串操作的通用函數,例如尋找和擷取子字串,以及模式比對。在 Lua 中對字串進行索引時,第一個字元位於位置 1(而不是 C 中的 0)。允許使用負索引,並將其解釋為從字串結尾向後索引。因此,最後一個字元位於位置 -1,依此類推。
字串函式庫在其表格 string 中提供所有函數。它還為字串設定一個元表格,其中 __index 欄位指向 string 表格。因此,您可以使用物件導向風格的字串函數。例如,string.byte(s, i) 可以寫成 s:byte(i)
string.byte({s} [, {i} [, {j}]]) string.byte()
傳回字元 s[i]s[i+1],..., s[j] 的內部數值代碼。{i} 的預設值是 1;{j} 的預設值是 {i}
請注意,數值代碼不一定在各個平台上都可攜帶。
string.char({...}) string.char()
接收零個或多個整數。傳回一個字串,其長度等於引數的數量,其中每個字元的內部數值代碼等於其對應的引數。
請注意,數值代碼不一定在各個平台上都可攜帶。
string.dump({function}) string.dump()
傳回一個包含給定函式二進位表示法的字串,以便之後對此字串使用 loadstring() 時,傳回該函式的副本。 {function} 必須是沒有上值的 Lua 函式。
string.find({s}, {pattern} [, {init} [, {plain}]]) string.find()
在字串 {s} 中尋找 {pattern} 的第一個匹配項。如果找到匹配項,則 {find} 會傳回此匹配項在 {s} 中開始和結束的索引;否則,它會傳回 nil。第三個可選數值引數 {init} 指定從哪裡開始搜尋;其預設值為 1,且可為負數。第四個可選引數 {plain} 的值為 {true} 時,會關閉樣式匹配功能,因此函式會執行純粹的「尋找子字串」操作,且 {pattern} 中的任何字元都不會被視為「魔術字元」。請注意,如果指定了 {plain},則也必須指定 {init}
如果樣式具有捕獲,則在成功匹配時,也會傳回捕獲的值,在兩個索引之後傳回。
string.format({formatstring}, {...}) string.format()
傳回其可變數量引數的格式化版本,格式化的方式遵循其第一個引數(必須是字串)中給定的描述。格式字串遵循標準 C 函式的 printf 系列的相同規則。唯一的區別在於不支援選項/修飾符 *lLnph,並且有一個額外的選項 qq 選項會以適合 Lua 直譯器安全讀回的形式格式化字串:字串會寫在雙引號之間,並且字串中的所有雙引號、換行符、內嵌的零和反斜線在寫入時都會正確逸出。例如,呼叫
string.format('%q', 'a string with "quotes" and \n new line')
將產生字串
"a string with \"quotes\" and \
 new line"
選項 cdEefgGiouXx 都需要一個數字作為引數,而 qs 則需要一個字串。
此函式不接受包含內嵌零的字串值。
string.gmatch({s}, {pattern}) string.gmatch()
傳回一個 迭代器 函式,每次呼叫它時,都會從字串 {s} 傳回 {pattern} 的下一個捕獲。
如果 {pattern} 未指定任何捕獲,則每次呼叫都會產生整個匹配項。
例如,以下迴圈
s = "hello world from Lua"
for w in string.gmatch(s, "%a+") do
  print(w)
end
將迭代字串 {s} 中的所有單字,並在每行中列印一個單字。下一個範例將給定字串中的所有 key=value 對收集到一個表格中
t = {}
s = "from=world, to=Lua"
for k, v in string.gmatch(s, "(%w+)=(%w+)") do
  t[k] = v
end
string.gsub({s}, {pattern}, {repl} [, {n}]) string.gsub()
傳回 {s} 的副本,其中所有 {pattern} 的出現次數都已替換為 {repl} 指定的替換字串,該字串可以是字串、表格或函式。 gsub 也會傳回它作為第二個值所做的替換總數。
如果 {repl} 是字串,則其值會用於替換。字元 % 會作為逸出字元:{repl} 中任何形式為 %n 的序列(其中 {n} 介於 1 和 9 之間),都代表第 {n} 個捕獲的子字串的值(請參閱下文)。序列 %0 代表整個匹配項。序列 %% 代表單個 %
如果 {repl} 是表格,則會針對每次匹配查詢該表格,並將第一個捕獲用作索引鍵;如果樣式未指定任何捕獲,則整個匹配項會用作索引鍵。
如果 {repl} 是函式,則每次發生匹配時都會呼叫此函式,並將所有捕獲的子字串依序傳遞為引數;如果樣式未指定任何捕獲,則會將整個匹配項作為單一引數傳遞。
如果表格查詢或函式呼叫傳回的值是字串或數字,則會將其用作替換字串;否則,如果它是 falsenil,則不會進行替換(也就是說,原始匹配項會保留在字串中)。
可選的最後一個參數 {n} 會限制發生的最大替換次數。例如,當 {n} 為 1 時,只會替換 pattern 的第一個出現次數。
以下是一些範例
x = string.gsub("hello world", "(%w+)", "%1 %1")
--> x="hello hello world world"
x = string.gsub("hello world", "%w+", "%0 %0", 1)
--> x="hello hello world"
x = string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1")
--> x="world hello Lua from"
x = string.gsub("home = $HOME, user = $USER", "%$(%w+)", os.getenv)
--> x="home = /home/roberto, user = roberto"
x = string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s)
      return loadstring(s)()
    end)
--> x="4+5 = 9"
local t = {name="lua", version="5.1"}
x = string.gsub("$name%-$version.tar.gz", "%$(%w+)", t)
--> x="lua-5.1.tar.gz"
string.len({s}) string.len()
接收字串並傳回其長度。空字串 "" 的長度為 0。會計算內嵌的零,因此 "a\000b\000c" 的長度為 5。
string.lower({s}) string.lower()
接收字串,並傳回該字串的副本,其中所有大寫字母都變更為小寫字母。所有其他字元都保持不變。大寫字母的定義取決於目前的地區設定。
string.match({s}, {pattern} [, {init}]) string.match()
在字串 {s} 中尋找 {pattern} 的第一個 match。如果找到一個,則 match 會傳回樣式的捕獲;否則,它會傳回 nil。如果 {pattern} 未指定任何捕獲,則會傳回整個匹配項。第三個可選數值引數 {init} 指定從哪裡開始搜尋;其預設值為 1,且可為負數。
string.rep({s}, {n}) string.rep()
傳回一個字串,該字串是字串 {s}{n} 個副本的串連。
string.reverse({s}) string.reverse()
傳回一個字串,該字串是字串 {s} 的反轉。
string.sub({s}, {i} [, {j}]) string.sub()
傳回 {s} 的子字串,該子字串從 {i} 開始,並持續到 {j}{i}{j} 可以是負數。如果 {j} 不存在,則會假定其等於 -1(與字串長度相同)。特別是,呼叫 string.sub(s,1,j) 會傳回長度為 {j}{s} 的前綴,而 string.sub(s,-i) 會傳回長度為 {i}{s} 的後綴。
string.upper({s}) string.upper()
接收字串,並傳回該字串的副本,其中所有小寫字母都變更為大寫字母。所有其他字元都保持不變。小寫字母的定義取決於目前的地區設定。

5.4.1 樣式 lua-patterns

字元類別用於表示一組字元。以下組合允許用於描述字元類別
x(其中 x 不是魔術字元 ^$()%.[]*+-? 之一)表示字元 x 本身。
.(點)表示所有字元。
%a 表示所有字母。
%c 表示所有控制字元。
%d 表示所有數字。
%l 表示所有小寫字母。
%p 表示所有標點符號字元。
%s 表示所有空格字元。
%u 表示所有大寫字母。
%w 表示所有字母數字字元。
%x 表示所有十六進位數字。
%z 表示表示法為 0 的字元。
%x(其中 x 是任何非字母數字字元)表示字元 x。這是逸出魔術字元的標準方式。任何標點符號字元(甚至是沒有魔術的字元)在用於表示模式中的字元本身時,前面都可以加上 %
[set] 表示類別,它是 set 中所有字元的聯集。可以使用 - 分隔範圍的結束字元,以指定字元範圍。上述描述的所有類別 %x 也可以用作 set 中的元件。 set 中的所有其他字元都代表它們自己。例如,[%w_](或 [_%w])表示所有字母數字字元加上底線,[0-7] 表示八進位數字,而 [0-7%l%-] 表示八進位數字加上小寫字母加上 - 字元。
未定義範圍與類別之間的互動。因此,[%a-z][a-%%] 之類的樣式沒有意義。
[^set] 表示 set 的補集,其中 set 的解讀方式如上所述。
對於以單個字母表示的所有類別(%a%c 等),對應的大寫字母表示該類別的補集。例如,%S 表示所有非空格字元。
字母、空格和其他字元群組的定義取決於目前的地區設定。特別是,類別 [a-z] 可能不等於 %l

樣式項目 lua-patternitem

樣式項目可以是
單個字元類別,符合類別中的任何單個字元;
後接 * 的單個字元類別,符合類別中字元的 0 個或多個重複。這些重複項目將始終符合可能的最長序列;
後接 + 的單個字元類別,符合類別中字元的 1 個或多個重複。這些重複項目將始終符合可能的最長序列;
後接 - 的單個字元類別,也符合類別中字元的 0 個或多個重複。與 * 不同,這些重複項目將始終符合可能的最短序列;
後接 ? 的單個字元類別,符合類別中字元的 0 個或 1 個出現次數;
%n,其中 n 介於 1 到 9 之間;此項目會匹配與第 n 個捕獲字串相等的子字串(請參閱下文);
%bxy,其中 xy 是兩個不同的字元;此項目會匹配以 x 開頭、以 y 結尾,且 xy 是平衡的字串。這表示,如果從左到右讀取字串,x 記為 +1y 記為 -1,則結尾的 y 是計數達到 0 的第一個 y。例如,項目 %b() 會匹配具有平衡括號的表達式。

模式 lua-pattern

模式是一連串的模式項目。模式開頭的 ^ 會將匹配錨定在主體字串的開頭。模式結尾的 $ 會將匹配錨定在主體字串的結尾。在其他位置,^$ 沒有特殊意義,而是代表它們自己。

捕獲 lua-capture

模式可能包含以括號括住的子模式;它們描述捕獲。當匹配成功時,主體字串中與捕獲匹配的子字串會被儲存(捕獲)以供未來使用。捕獲會根據其左括號進行編號。例如,在模式 "(a*(.)%w(%s*))" 中,與 "a*(.)%w(%s*)" 匹配的字串部分會被儲存為第一個捕獲(因此編號為 1);與 . 匹配的字元會被捕獲為編號 2,而與 %s* 匹配的部分則會被捕獲為編號 3。
作為一種特殊情況,空捕獲 () 會捕獲目前的字串位置(一個數字)。例如,如果我們在字串 "flaaap" 上應用模式 "()aa()",將會有兩個捕獲:3 和 5。
模式不能包含嵌入的零。請改用 %z

5.5 表格操作 lua-lib-table

此函式庫提供用於表格操作的通用函式。它將所有函式提供在表格 table 內。
表格函式庫中的大多數函式都假設表格表示陣列或列表。對於這些函式,當我們談到表格的「長度」時,我們指的是長度運算子的結果。
table.concat({table} [, {sep} [, {i} [, {j}]]]) table.concat()
給定一個所有元素都是字串或數字的陣列,會回傳 table[i]..sep..table[i+1] ... sep..table[j]{sep} 的預設值為空字串,{i} 的預設值為 1,而 {j} 的預設值為表格的長度。如果 {i} 大於 {j},則會回傳空字串。
table.foreach({table}, {f}) table.foreach()
{table} 的所有元素執行給定的 {f}。對於每個元素,會以索引和對應的值作為引數呼叫 {f}。如果 {f} 回傳非 `nil` 值,則會中斷迴圈,並將此值作為 table.foreach 的最終值回傳。
有關表格遍歷的額外資訊,請參閱 next()
table.foreachi({table}, {f}) table.foreachi()
{table} 的數值索引執行給定的 {f}。對於每個索引,會以索引和對應的值作為引數呼叫 {f}。索引會依序從 1 遍歷到 n,其中 n 是表格的長度。如果 {f} 回傳非 `nil` 值,則會中斷迴圈,並將此值作為 table.foreachi 的結果回傳。
table.insert({table}, [{pos},] {value}) table.insert()
將元素 {value} 插入到 {table} 中的位置 {pos},如有必要,會將其他元素向上移動以騰出空間。{pos} 的預設值為 n+1,其中 n 是表格的長度(請參閱 lua-length),因此呼叫 table.insert(t,x) 會將 x 插入到表格 t 的末尾。
table.maxn({table}) table.maxn()
回傳給定表格的最大正數值索引,如果表格沒有正數值索引,則回傳零。(為執行其工作,此函式會對整個表格執行線性遍歷。)
table.remove({table} [, {pos}]) table.remove()
{table} 中移除位置 {pos} 的元素,如有必要,會將其他元素向下移動以關閉空間。回傳移除元素的值。{pos} 的預設值為 n,其中 n 是表格的長度(請參閱 lua-length),因此呼叫 table.remove(t) 會移除表格 t 的最後一個元素。
table.sort({table} [, {comp}]) table.sort()
依給定順序對表格元素進行 in-place 排序,從 table[1]table[n],其中 n 是表格的長度(請參閱 lua-length)。如果給定 {comp},則它必須是一個接收兩個表格元素,且當第一個元素小於第二個元素時回傳 true 的函式(因此排序後 not comp(a[i+1],a[i]) 將會是 true)。如果未給定 {comp},則會改用標準 Lua 運算子 <
排序演算法「不是」穩定的,也就是說,依給定順序被視為相等的元素可能會在排序後改變其相對位置。

5.6 數學函式 lua-lib-math

此函式庫是標準 C 數學函式庫中大多數函式的介面。它將所有函式提供在表格 math 內。
math.abs({x}) math.abs()
回傳 {x} 的絕對值。
math.acos({x}) math.acos()
回傳 {x} 的反餘弦(以弧度為單位)。
math.asin({x}) math.asin()
回傳 {x} 的反正弦(以弧度為單位)。
math.atan({x}) math.atan()
回傳 {x} 的反正切(以弧度為單位)。
math.atan2({x}, {y}) math.atan2()
回傳 x/y 的反正切(以弧度為單位),但會使用兩個參數的符號來找出結果的象限。(它也會正確處理 {y} 為零的情況。)
math.ceil({x}) math.ceil()
回傳大於或等於 {x} 的最小整數。
math.cos({x}) math.cos()
回傳 {x} 的餘弦(假設以弧度為單位)。
math.cosh({x}) math.cosh()
回傳 {x} 的雙曲餘弦。
math.deg({x}) math.deg()
回傳以度為單位的角度 {x}(以弧度為單位給定)。
math.exp({x}) math.exp()
回傳值 e^x
math.floor({x}) math.floor()
回傳小於或等於 {x} 的最大整數。
math.fmod({x}, {y}) math.fmod()
回傳 {x} 除以 {y} 的餘數。
math.frexp({x}) math.frexp()
回傳 me,使得 x = m * 2^ee 是整數,且 m 的絕對值在範圍 [0.5, 1) 內(當 {x} 為零時為零)。
math.huge math.huge
HUGE_VAL,一個大於或等於任何其他數值的值。
math.ldexp({m}, {e}) math.ldexp()
回傳 m * 2^ee 應該是整數)。
math.log({x}) math.log()
回傳 {x} 的自然對數。
math.log10({x}) math.log10()
回傳 {x} 的以 10 為底的對數。
math.max({x}, {...}) math.max()
回傳其引數中的最大值。
math.min({x}, {...}) math.min()
回傳其引數中的最小值。
math.modf({x}) math.modf()
回傳兩個數字,即 {x} 的整數部分和 {x} 的小數部分。
math.pi math.pi
pi 的值。
math.pow({x}, {y}) math.pow()
回傳 x^y。(您也可以使用表達式 x^y 來計算此值。)
math.rad({x}) math.rad()
回傳以弧度為單位的角度 {x}(以度為單位給定)。
math.random([{m} [, {n}]]) math.random()
此函式是 ANSI C 提供的簡單虛擬亂數產生器函式 rand 的介面。(無法保證其統計屬性。)
當不帶參數呼叫時,會回傳一個範圍在 [0,1) 的偽隨機實數。當帶有一個數字 {m} 呼叫時,math.random 會回傳一個範圍在 [1, m] 的偽隨機整數。當帶有兩個數字 {m}{n} 呼叫時,math.random 會回傳一個範圍在 [m, n] 的偽隨機整數。
math.randomseed({x}) math.randomseed()
{x} 設定為偽隨機產生器的「種子」:相同的種子會產生相同的數字序列。
math.sin({x}) math.sin()
回傳 {x} 的正弦值(假設 {x} 以弧度為單位)。
math.sinh({x}) math.sinh()
回傳 {x} 的雙曲正弦值。
math.sqrt({x}) math.sqrt()
回傳 {x} 的平方根。(您也可以使用運算式 x^0.5 來計算此值。)
math.tan({x}) math.tan()
回傳 {x} 的正切值(假設 {x} 以弧度為單位)。
math.tanh({x}) math.tanh()
回傳 {x} 的雙曲正切值。

5.6 輸入和輸出工具 lua-lib-io

I/O 函式庫提供了兩種不同的檔案操作方式。第一種使用隱含的檔案描述符;也就是說,有一些操作可以設定預設的輸入檔案和預設的輸出檔案,而所有的輸入/輸出操作都針對這些預設檔案。第二種方式使用顯式的檔案描述符。
當使用隱含的檔案描述符時,所有操作都由表格 io 提供。當使用顯式的檔案描述符時,操作 io.open 會回傳一個檔案描述符,然後所有操作都作為檔案描述符的方法提供。
表格 io 也提供了三個預定義的檔案描述符,它們的含義與 C 語言中的相同:io.stdinio.stdoutio.stderr
除非另有說明,所有 I/O 函式在失敗時回傳 nil(外加一個錯誤訊息作為第二個結果),而在成功時回傳一個與 nil 不同的值。
io.close([{file}]) io.close()
等同於 file:close。如果沒有 {file},則關閉預設的輸出檔案。
io.flush() io.flush()
等同於對預設輸出檔案執行 file:flush
io.input([{file}]) io.input()
當使用檔案名稱呼叫時,它會開啟指定的檔案(以文字模式),並將其句柄設定為預設的輸入檔案。當使用檔案句柄呼叫時,它只會將此檔案句柄設定為預設的輸入檔案。當不帶參數呼叫時,它會回傳目前的預設輸入檔案。
如果發生錯誤,此函式會引發錯誤,而不是回傳錯誤代碼。
io.lines([{filename}]) io.lines()
以讀取模式開啟指定的檔案名稱,並回傳一個迭代器函式,每次呼叫它時,都會從檔案回傳新的一行。因此,結構
for line in io.lines(filename) do body end
將會迭代檔案的所有行。當迭代器函式偵測到檔案結尾時,它會回傳 nil(以結束迴圈)並自動關閉檔案。
呼叫 io.lines()(不帶檔案名稱)等同於 io.input():lines();也就是說,它會迭代預設輸入檔案的行。在這種情況下,當迴圈結束時,它不會關閉檔案。
io.open({filename} [, {mode}]) io.open()
此函式會依照字串 {mode} 中指定的模式開啟檔案。它會回傳一個新的檔案句柄,或者,如果發生錯誤,則會回傳 nil 外加一個錯誤訊息。
{mode} 字串可以是下列任何一個
"r" 讀取模式(預設);
"w" 寫入模式;
"a" 附加模式;
"r+" 更新模式,保留所有先前資料;
"w+" 更新模式,清除所有先前資料;
"a+" 附加更新模式,保留先前資料,只允許在檔案結尾寫入。
{mode} 字串的結尾也可以有一個 b,在某些系統中,需要使用它才能以二進位模式開啟檔案。這個字串與標準 C 函式 fopen 中使用的字串完全相同。
io.output([{file}]) io.output()
io.input 類似,但操作的是預設的輸出檔案。
io.popen({prog} [, {mode}]) io.popen()
在單獨的程序中啟動程式 {prog},並回傳一個檔案句柄,您可以使用它來從此程式讀取資料(如果 {mode}"r",預設值)或將資料寫入此程式(如果 {mode}"w")。
此函式與系統相關,並非在所有平台上都可用。
io.read({...}) io.read()
等同於 io.input():read
io.tmpfile() io.tmpfile()
回傳一個臨時檔案的句柄。此檔案以更新模式開啟,並且在程式結束時會自動移除。
io.type({obj}) io.type()
檢查 {obj} 是否為有效的檔案句柄。如果 {obj} 是已開啟的檔案句柄,則回傳字串 "file";如果 {obj} 是已關閉的檔案句柄,則回傳 "closed file";如果 {obj} 不是檔案句柄,則回傳 nil
io.write({...}) io.write()
等同於 io.output():write
file:close() file:close()
關閉 file。請注意,當檔案句柄被垃圾回收時,檔案會自動關閉,但這需要不可預測的時間才會發生。
file:flush() file:flush()
將所有寫入的資料儲存到 file
file:lines() file:lines()
回傳一個迭代器函式,每次呼叫它時,都會從檔案回傳新的一行。因此,結構
for line in file:lines() do body end
將會迭代檔案的所有行。(與 io.lines 不同,此函式不會在迴圈結束時關閉檔案。)
file:read({...}) file:read()
依照給定的格式讀取檔案 file,這些格式指定要讀取的內容。對於每個格式,函式會回傳一個包含讀取字元的字串(或數字),如果無法使用指定的格式讀取資料,則回傳 nil。當不帶格式呼叫時,它會使用預設格式來讀取整個下一行(請參閱下文)。
可用的格式為
"*n" 讀取一個數字;這是唯一一個會回傳數字而不是字串的格式。 "*a" 從目前位置開始讀取整個檔案。在檔案結尾時,它會回傳空字串。 "*l" 讀取下一行(跳過行尾符號),在檔案結尾時回傳 nil。這是預設格式。 number 讀取一個最多包含該數字的字元數的字串,在檔案結尾時回傳 nil。如果 number 為零,則不讀取任何內容,並回傳空字串,或在檔案結尾時回傳 nil
file:seek([{whence}] [, {offset}]) file:seek()
設定和取得檔案位置,從檔案開頭算起,到由 {offset} 加一個由字串 {whence} 指定的基礎位置的位置,如下所示
"set":基礎位置是 0(檔案開頭);
"cur":基礎位置是目前位置;
"end":基礎位置是檔案結尾;
如果成功,函式 seek 會回傳最終的檔案位置,以從檔案開頭算起的位元組為單位。如果此函式失敗,則會回傳 nil,外加一個描述錯誤的字串。
{whence} 的預設值為 "cur",而 {offset} 的預設值為 0。因此,呼叫 file:seek() 會回傳目前的檔案位置,而不變更它;呼叫 file:seek("set") 會將位置設定為檔案開頭(並回傳 0);而呼叫 file:seek("end") 會將位置設定為檔案結尾,並回傳其大小。
file:setvbuf({mode} [, {size}]) file:setvbuf()
設定輸出檔案的緩衝模式。有三種可用的模式
"no" 無緩衝;任何輸出操作的結果都會立即出現。 "full" 完全緩衝;只有當緩衝區已滿時(或當您明確 flush 檔案時(請參閱io.flush())才會執行輸出操作。 "line" 行緩衝;輸出會緩衝,直到輸出換行符號,或從某些特殊檔案(例如終端設備)有任何輸入為止。
對於最後兩種情況,{size} 會指定緩衝區的大小,以位元組為單位。預設值為適當的大小。
file:write({...}) file:write()
將每個引數的值寫入 file。引數必須是字串或數字。若要寫入其他值,請在 write 之前使用 tostring tostring()string.format string.format()

5.8 作業系統工具 lua-lib-os

此函式庫是透過表格 os 實作。
os.clock() os.clock()
回傳程式所使用 CPU 時間的秒數近似值。
os.date([{format} [, {time}]]) os.date()
回傳一個字串或一個表格,其中包含根據給定的字串 {format} 格式化的日期和時間。
如果存在 {time} 引數,則這是要格式化的時間(請參閱 os.time 函式 os.time() 以了解此值的說明)。否則,date 會格式化目前時間。
如果 {format}! 開頭,則日期會以協調世界時格式化。在此選擇性字元之後,如果 {format} 是字串 "*t",則 date 會回傳一個包含下列欄位的表格:year(四位數字)、month(1-12)、day(1-31)、hour(0-23)、min(0-59)、sec(0-61)、wday(星期幾,星期日是 1)、yday(一年中的第幾天)和 isdst(日光節約旗標,一個布林值)。
如果 {format} 不是 "*t",則 date 會回傳以字串表示的日期,並依照與 C 函式 strftime 相同的規則格式化。
當不帶引數呼叫時,date 會回傳合理的日期和時間表示形式,這取決於主機系統和目前的地區設定(也就是說,os.date() 等同於 os.date("%c"))。
os.difftime({t2}, {t1}) os.difftime()
回傳從時間 {t1} 到時間 {t2} 的秒數。在 POSIX、Windows 和其他某些系統中,此值完全等於 t2 - t1
os.execute([{command}]) os.execute()
此函式等同於 C 函式 system。它會將 {command} 傳遞給作業系統 Shell 執行。它會回傳一個狀態碼,該狀態碼與系統相關。如果沒有 {command},則在 Shell 可用的情況下會回傳非零值,否則會回傳零。
os.exit([{code}]) os.exit()
呼叫 C 函式 exit,並帶有可選的 {code},以終止主機程式。{code} 的預設值為成功代碼。
os.getenv({varname}) os.getenv()
回傳程序環境變數 {varname} 的值,如果變數未定義,則回傳 nil
os.remove({filename}) os.remove()
刪除具有給定名稱的檔案。目錄必須為空才能刪除。如果此函式失敗,則會回傳 nil,以及描述錯誤的字串。
os.rename({oldname}, {newname}) os.rename()
將名為 {oldname} 的檔案重新命名為 {newname}。如果此函式失敗,則會回傳 nil,以及描述錯誤的字串。
os.setlocale({locale} [, {category}]) os.setlocale()
設定程式目前的地區設定。{locale} 是一個指定地區設定的字串;{category} 是一個可選的字串,描述要變更的類別:"all""collate""ctype""monetary""numeric""time";預設類別為 "all"。此函式會回傳新的地區設定名稱,如果無法滿足請求,則回傳 nil
os.time([{table}]) os.time()
在沒有引數的情況下呼叫時,回傳目前時間,或者回傳代表給定表格指定的日期和時間的時間。此表格必須具有欄位 yearmonthday,並且可以具有欄位 hourminsecisdst(有關這些欄位的描述,請參閱 os.date 函式 os.date())。
回傳的值是一個數字,其含義取決於您的系統。在 POSIX、Windows 和其他一些系統中,此數字計算自給定開始時間(「紀元」)以來的秒數。在其他系統中,未指定其含義,並且 time 回傳的數字只能作為 datedifftime 的引數使用。
os.tmpname() os.tmpname()
回傳一個字串,其中包含可用於暫存檔的檔案名稱。該檔案必須在使用前明確開啟,並且在不再需要時明確刪除。

5.9 除錯函式庫 lua-lib-debug

此函式庫提供除錯介面給 Lua 程式的功能。您在使用此函式庫時應謹慎。此處提供的函式應專門用於除錯和類似任務,例如效能分析。請克制將其用作一般程式設計工具的誘惑:它們可能非常慢。此外,它的幾個函式違反了關於 Lua 程式碼的一些假設(例如,無法從外部存取函式的區域變數,或者 Lua 程式碼無法變更使用者資料的元表),因此可能會損害原本安全的程式碼。
此函式庫中的所有函式都在 debug 表格內提供。所有在執行緒上運作的函式都有一個可選的第一個引數,它是要操作的執行緒。預設值始終是目前的執行緒。
debug.debug() debug.debug()
進入與使用者互動的模式,執行使用者輸入的每個字串。透過使用簡單的命令和其他除錯工具,使用者可以檢查全域和區域變數、變更其值、評估運算式等等。僅包含單字 cont 的行會結束此函式,以便呼叫者繼續執行。
請注意,debug.debug 的命令在任何函式中都不是詞法巢狀的,因此無法直接存取區域變數。
debug.getfenv(o) debug.getfenv()
回傳物件 {o} 的環境。
debug.gethook([{thread}]) debug.gethook()
以三個值的形式回傳執行緒的目前 Hook 設定:目前的 Hook 函式、目前的 Hook 遮罩,以及目前的 Hook 計數(由 debug.sethook 函式設定)。
debug.getinfo([{thread},] {function} [, {what}]) debug.getinfo()
回傳包含有關函式資訊的表格。您可以直接給定函式,也可以給定一個數字作為 {function} 的值,這表示在給定執行緒的呼叫堆疊的 {function} 層級執行的函式:層級 0 是目前的函式(getinfo 本身);層級 1 是呼叫 getinfo 的函式;依此類推。如果 {function} 是一個大於活動函式數量的數字,則 getinfo 會回傳 nil
回傳的表格可能包含 lua_getinfo 回傳的所有欄位(請參閱 lua_getinfo()),其中字串 {what} 描述要填寫的欄位。{what} 的預設值是取得所有可用的資訊,但有效的行表格除外。如果存在,選項 f 會新增一個名為 func 的欄位,其中包含函式本身。如果存在,選項 L 會新增一個名為 activelines 的欄位,其中包含有效行的表格。
例如,運算式 debug.getinfo(1,"n").name 會回傳目前函式的名稱(如果可以找到合理的名稱),而 debug.getinfo(print) 會回傳一個包含有關 print 函式的所有可用資訊的表格。
debug.getlocal([{thread},] {level}, {local}) debug.getlocal()
此函式會回傳堆疊 {level} 層級的函式的索引 {local} 的區域變數的名稱和值。(第一個參數或區域變數的索引為 1,依此類推,直到最後一個活動的區域變數。)如果沒有具有給定索引的區域變數,則函式會回傳 nil,並且在呼叫的 {level} 超出範圍時會引發錯誤。(您可以呼叫 debug.getinfo debug.getinfo() 以檢查層級是否有效。)
( (左括號) 開頭的變數名稱表示內部變數 (迴圈控制變數、暫時變數和 C 函式區域變數)。
debug.getmetatable({object}) debug.getmetatable()
回傳給定 {object} 的元表,如果它沒有元表,則回傳 nil
debug.getregistry() debug.getregistry()
回傳登錄表格(請參閱 lua-registry)。
debug.getupvalue({func}, {up}) debug.getupvalue()
此函式會回傳函式 {func} 的索引 {up} 的上值名稱和值。如果沒有具有給定索引的上值,則函式會回傳 nil
debug.setfenv({object}, {table}) debug.setfenv()
將給定 {object} 的環境設定為給定 {table}。回傳 {object}
debug.sethook([{thread},] {hook}, {mask} [, {count}]) debug.sethook()
將給定函式設定為 Hook。字串 {mask} 和數字 {count} 描述何時呼叫 Hook。字串遮罩可以具有以下字元,並具有給定的含義
"c":每次 Lua 呼叫函式時,都會呼叫 Hook;
"r":每次 Lua 從函式回傳時,都會呼叫 Hook;
"l":每次 Lua 進入新的程式碼行時,都會呼叫 Hook。
如果 {count} 不等於零,則在每執行 {count} 個指令後,都會呼叫 Hook。
在沒有引數的情況下呼叫時,debug.sethook 會關閉 Hook。
呼叫 Hook 時,它的第一個參數是一個描述觸發其呼叫的事件的字串:"call""return"(或「tail return」)、"line""count"。對於行事件,Hook 也會取得新行號作為其第二個參數。在 Hook 內部,您可以使用層級 2 呼叫 getinfo,以取得有關執行函式的更多資訊(層級 0 是 getinfo 函式,層級 1 是 Hook 函式),除非事件是 "tail return"。在這種情況下,Lua 只會模擬回傳,呼叫 getinfo 會回傳無效的資料。
debug.setlocal([{thread},] {level}, {local}, {value}) debug.setlocal()
此函式會將值 {value} 指派給堆疊 {level} 層級的函式的索引 {local} 的區域變數。如果沒有具有給定索引的區域變數,則函式會回傳 nil,並且在呼叫的 {level} 超出範圍時會引發錯誤。(您可以呼叫 getinfo 來檢查層級是否有效。)否則,它會回傳區域變數的名稱。
debug.setmetatable({object}, {table}) debug.setmetatable()
將給定 {object} 的元表設定為給定 {table}(它可以是 nil)。
debug.setupvalue({func}, {up}, {value}) debug.setupvalue()
此函式會將值 {value} 指派給函式 {func} 的索引 {up} 的上值。如果沒有具有給定索引的上值,則函式會回傳 nil。否則,它會回傳上值的名稱。
debug.traceback([{thread},] [{message} [,{level}]]) debug.traceback()
回傳一個包含呼叫堆疊追蹤的字串。追蹤的開頭會附加一個可選的 {message} 字串。可選的 {level} 數字會告知從哪個層級開始追蹤(預設值為 1,即呼叫 traceback 的函式)。

參考書目 lua-ref-bibliography

此說明文件是從主要參考文獻稍作修改的版本
R. Ierusalimschy, L. H. de Figueiredo, 和 W. Celes., "Lua: 5.1 參考手冊", https://lua.dev.org.tw/manual/5.1/manual.html
以下參考文獻中討論了 Lua
R. Ierusalimschy, L. H. de Figueiredo, 和 W. Celes., "Lua --- 一種可擴展的擴充語言"。 "Software: Practice & Experience" 26, 6 (1996) 635-652。
L. H. de Figueiredo, R. Ierusalimschy, 和 W. Celes., "一種用於擴充應用程式的語言之設計與實作"。 "Proc. of XXI Brazilian Seminar on Software and Hardware" (1994) 273-283。
L. H. de Figueiredo, R. Ierusalimschy, 和 W. Celes., "Lua: 一種可擴展的嵌入式語言"。 "Dr. Dobb's Journal" 21, 12 (1996年12月) 26-33。
R. Ierusalimschy, L. H. de Figueiredo, 和 W. Celes., "一種擴充語言的演進:Lua 的歷史"。 "Proc. of V Brazilian Symposium on Programming Languages" (2001) B-14-B-28。
此說明文件與 Lua 5.1 及 Lua 5.1 手冊具有相同的版權和授權
版權 (c) 1994-2006 Lua.org, PUC-Rio。
特此授予任何取得本軟體及相關文件檔案(以下稱「軟體」)副本的人員免費許可,以在不受限制的情況下處理本軟體,包括但不限於使用、複製、修改、合併、發佈、散布、再授權及/或銷售本軟體副本的權利,並允許向取得本軟體的人員授予這些權利,但須符合以下條件
上述版權聲明和本許可聲明應包含在本軟體的所有副本或主要部分中。
本軟體按「現狀」提供,不作任何明示或暗示的擔保,包括但不限於對適銷性、特定用途適用性和不侵權的擔保。在任何情況下,作者或版權持有人均不對任何索賠、損害或其他責任承擔責任,無論該責任是因合約行為、侵權行為或其他原因而產生,皆與本軟體或本軟體的使用或其他交易有關。

C LUAREF 文件 lua-ref-doc

這是一個包含 Lua 5.1 參考文獻的 Vim 說明文件,它(除了少數例外和調整外)是 Lua 5.1 參考手冊的副本(請參閱 lua-ref-bibliography)。有關使用資訊,請參閱 lua-ref-doc。有關版權資訊,請參閱 lua-ref-copyright
關於如何實作此參考文獻的主要想法和概念取自 Christian Habermann 的 CRefVim 專案 (https://www.vim.org/scripts/script.php?script_id=614)。
改編用於捆綁的 Nvim 文件;原始插件位於 https://www.vim.org/scripts/script.php?script_id=1291
主要
指令索引
快速參考