Lua4.0 參考手冊(三)4.5

(接上篇)
-------------------
4.5 表達式
-------------------
---------
4.5.1 基本表達式
---------
Lua 中基本表達式是:
    exp ::= `(' exp `)'
    exp ::= nil
    exp ::= number
    exp ::= literal
    exp ::= var
    exp ::= upvalue
    exp ::= function
    exp ::= functioncall
    exp ::= tableconstructor
數值(數值常量)和字符串常量在 4.1 節解釋過了。變量在 4.4.2 節解釋過了。upvalue 在 4.6 節解釋。函數定義在 4.5.9 節解釋。函數調用在 4.5.8 節解釋。表的構造函數在 4.5.7 節解釋。

一個全局變量 x 的調用等價於調用 getglobal("x"),一個下標變量 t[i] 等價於 gettable_event(t,i) 。這些函數的解釋參見 4.8 節(getglobal 在基礎的庫中,gettable_event 僅用於解釋目的)。

非終結的 exp1 被用來指示一個表達式的返回值必須被調整爲一個值:
    exp1 ::= exp

---------
4.5.2 算術運算符
---------
Lua 支持常見的算術運算符。這些運算符是二元操做符 +(加), -(減), *(乘), /(除) 和 ^(冪),一元操做符 -(負)。若是操做數是數值,或者是能夠轉化爲數值的字符串(根據 4.2 節中給出的規則),全部的操做(除了冪操做)具備一般意義。不然,一個適用的標籤函數(參見 4.8 節)將會被調用。冪操做將一直調用一個標籤函數。標準的數學庫以預想的意義重定義了冪操做(參見 6.3 節)。

---------
4.5.3 關係運算符
---------
Lua 中的關係運算符是:
    == ~= < > <= >=
他們返回 nil 作爲假,非 nil 作爲真。

相等(==)首先比較兩個操做數的標籤。若是不一樣,結果爲 nil。不然,比較它們的值。數值或字符串以常見的方式比較。表, userdata 和函數按引用比較,也就是說,兩個比較的表只有是同一個的時候才被認爲是相等的。不等運算 ~= 和相等運算 (==) 具備徹底相反的結果。

4.2 節的轉換規則不適用於相等比較。因此,"0"==0 的求值結果爲 false,t[0] 和 t["0"] 表示表中不一樣的元素。

順序比較操做符是這麼工做的:若是兩個參數都是數值,他們就以數值比較。若是兩個參數均可以轉化爲字符串,它們將以字典序比較。不然的話, 標籤方法 "lt" 將被調用(參見 4.8 節)。

---------
4.5.4 邏輯運算符
---------
Lua 中的邏輯運算符是:
    and or not
和控制結構同樣,全部的邏輯運算符認爲 nil 爲假而其它的都爲真。
合取運算符 and 返回 nil 若是它的第一個參數爲 nil;不然,它返回它的第二個參數。析取運算符 or 返回它的第一個參數若是它不一樣於 nil;不然,它返回它的第第二個參數。and 和 or 是短路求值,也就是說,第二個操做數只在須要的時候才被求值。

有兩個使用邏輯運算符的習慣用法。第一個是:
    x = x or v
它等價於
    if x == nil then x = v end
該用法當 x 未設置時給 x 設置一個默認值。
第二個習慣用法是:
    x = a and b or c
它應該被讀爲 x = (a and b) or c. 它等價於
    if a then x = b else x = c end
條件是 b 不爲 nil。

---------
4.5.5 鏈接
---------
Lua 中的字符串鏈接操做符由兩點「.." 表示。若是兩個操做數是字符串或者數字,他們按 4.2 節的規則轉化爲字符串。不然,標籤方法 "concat" 將被調用(參見 4.8 節)。

---------
4.5.6 優先級
---------
運算符的優先級以下表所示,從低到高排列:
    and or
    < > <= >= ~= ==
    ..
    + -
    * /
    not - (unary)
    ^
全部的二元操做符具體左結合性,^除外,冪操做具備右結合性。預編譯可能從新排列相關運算符(好比 .. 和 +)的求值順序,只要優化不改變正常的結果。反而,這些優化可能改變一些結果,若是你爲這些運算符定義了一些不相關的標籤方法。

---------
4.5.7 表的構造函數
---------
Table 的構造函數是建立表的表達式。當對構造函數求值的時候,會生成一個新的表。構造函數能夠用來新建一個空表,或者新建一個表並初始化一些字段。
構造函數的語法以下:
    tableconstructor ::= `{' fieldlist `}'
    fieldlist ::= lfieldlist | ffieldlist | lfieldlist `;' ffieldlist | ffieldlist `;' lfieldlist
    lfieldlist ::= [lfieldlist1]
    ffieldlist ::= [ffieldlist1]

lfieldlist1 被用來初始化列表。
    lfieldlist1 ::= exp {`,' exp} [`,']

列表中的表達式被賦值給一個連續的數值索引,索引從 1 開始。例如:
    a = {"v1", "v2", 34}
等同於:
    do
      local temp = {}
      temp[1] = "v1"
      temp[2] = "v2"
      temp[3] = 34
      a = temp
   end

ffieldlist1 初始化表中的其它字段:
    ffieldlist1 ::= ffield {`,' ffield} [`,']
    ffield ::= `[' exp `]' `=' exp | name `=' exp
例如:
    a = {[f(k)] = g(y), x = 1, y = 3, [0] = b+c}
等同於:
    do
      local temp = {}
      temp[f(k)] = g(y)
      temp.x = 1 -- or temp["x"] = 1
      temp.y = 3 -- or temp["y"] = 3
      temp[0] = b+c
      a = temp
    end

事實上, {x = 1, y = 4} 這樣的表達式是表達式 {["x"] = 1, ["y"] = 4} 的語法糖。

兩種形式均可以有一個可選的結尾逗號,而且在一樣的構造中能夠用分號分割。例如,下面的形式都是對的。
    x = {;}
    x = {"a", "b",}
    x = {type="list"; "a", "b"}
    x = {f(0), f(1), f(2),; n=3,}

---------
4.5.8 函數調用
---------
Lua 中的函數調用有以下語法:
    functioncall ::= varorfunc args
首先,varorfunc 被求值。若是它的值類型爲 function,這個函數就用給定的參數被調用。 不然,標籤方法 "function" 被調用,第一個參數爲 varorfunc  的值,以後是原來的調用參數(參見 4.8 節)。

形如:
    functioncall ::= varorfunc `:' name args
可被用來調用 "methods"。v:name(...) 調用是 v.name(v, ...) 的語法糖,除了 v 只被求值一次。

參數的語法以下:
    args ::= `(' [explist1] `)'
    args ::= tableconstructor
    args ::= literal
    explist1 ::= {exp1 `,'} exp

全部參數表達式在函數調用前被求值。f{...} 調用是 f({...}) 的語法糖,即,參數列表是一個新建的 table。f'...' (或者 f"..." 或者 f[[...]])調用是 f('...') 的語法糖,即,參數列表是一個字符串常量。

由於一個函數能夠返回任意多個值(參見 4.4.3 節),返回值的個數在使用以前必須進行調整(參見 4.3 節)。若是一個函數調用做爲語句使用(參見 4.4.5 節),它的返回結果會被調整到 0 個,於是返回值被所有丟棄。若是一個函數在須要一個值(語法中被表示爲非終結的 exp1)的地方調用,它的返回結果會被調整到 1 個,於是除了第一個返回值其它的都被丟棄。若是一個函數在須要多個值的地方調用(語法上表示爲非終結的 exp),不對返回結果個數進行調整。惟一能夠保持多個值的地方是賦值的最後(或惟一)一個表達式,參數列表中,或者在 return 語句中。這裏是一些例子:
    f() -- 調整到 0 個返回值
    g(f(), x) -- f() 調整到 1 個返回值
    g(x, f()) -- g 得到 x 和 f() 的全部返回值
    a,b,c = f(), x -- f() 調整到 1 個返回值 ( c 得到 nil )
    a,b,c = x, f() -- f() 調整到 2 個返回值
    a,b,c = f() -- f() 調整到 3 個返回值
    return f() -- 返回全部的 f() 的返回值
    return x,y,f() -- 返回 a, b, 和全部的 f() 的返回值

-------------------
4.5.9 函數定義
-------------------
函數定義的語法是:
    function ::= function `(' [parlist1] `)' block end
    stat ::= function funcname `(' [parlist1] `)' block end
    funcname ::= name | name `.' name | name `:' name

語句
    function f () ... end

    f = function () ... end
的語法糖。
語句
    function v.f () ... end

    v.f = function () ... end
的語法糖。

一個函數定義是一個可執行的表達式,它的值類型爲 function。當 Lua 預編譯一個 chunk,它全部的函數體也都會被預編譯。而後,當 Lua 執行函數定義,它的 upvalue 就是肯定的了(參見 4.6 節),函數也就實例化(或者閉合)了。這個函數實例(或者閉包)就是表達式的最終值。一樣函數的不一樣實例可能有不一樣的 upvalue 。

參數和局部變量的表現同樣,由參數值進行初始化。
    parlist1 ::= `...'
    parlist1 ::= name {`,' name} [`,' `...']
當一個函數被調用時,實參的個數被調整爲和形參同樣(參見 4.3 節),除非函數是可變參數函數(vararg function),也就是參數列表的最後是三個點('...')。一個可變參數函數不須要調整它的實參列表;而是把全部額外的實參收集到名爲 arg 的隱含參數中。arg 的值是一個表,它的一個字段 n 表示額外參數的個數,而且額外的參數位於 1, 2, ..., n 。

做爲一個例子,考慮下面的定義:
    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, arg={n=0}
  g(3, 4)    a=3, b=4, arg={n=0}
  g(3, 4, 5, 8) a=3, b=4, arg={5, 8; n=2}
  g(5, r()) a=5, b=1, arg={2, 3; n=2}

結果由 return 語句返回(見 4.4.3節)。若是執行到函數最後也沒有 return 指令的話,函數不返回值。

語法
    funcname ::= name `:' name
用來定義函數,函數有一個隱含的參數 self。

語句
    function v:f (...) ... end
只是
    v.f = function (self, ...) ... end
的語法糖。
注意函數得到一個額外的名爲 self 的形式參數。
(未完待續)閉包

相關文章
相關標籤/搜索