lua1 基礎1


html

 注:本記錄都摘錄自:http://manual.luaer.cn/ , lua在線手冊 。1-2.5部分。程序員


  1.  相似 C 的轉義符: '\a' (響鈴), '\b' (退格), '\f' (表單), '\n' (換行), '\r' (回車), '\t' (橫向製表), '\v' (縱向製表), '\\' (反斜槓), '\"' (雙引號), 以及 '\'' (單引號)。 數組

  2. 反斜槓加數字的形式 \ddd 來描述一個字符,注意,若是須要在這種描述方法後接一個是數字的字符, 那麼反斜槓後必須寫滿三個數字。閉包

    1.  下面五種方式描述了徹底相同的字符串:函數

      1.      a = 'alo\n123"'
             a = "alo\n123\""
             a = '\97lo\10\04923"'
             a = [[alo
             123"]]
             a = [==[
             alo
             123"]==]
  3. Lua 中有八種基本類型: nilbooleannumberstringfunction, userdatathread, and table.lua

    1. Boolean 類型只有兩種值:false 和 true。 nil 和 false 都能致使條件爲假;而另外全部的值都被看成真。spa

    2. Number 表示實數(雙精度浮點數)。操作系統

    3. userdata 類型用來將任意 C 數據保存在 Lua 變量中。 這個類型至關於一塊原生的內存,除了賦值和相同性判斷,Lua 沒有爲之預約義任何操做。 然而,經過使用 metatable (元表) ,程序員能夠爲 userdata 自定義一組操做。 userdata 不能在 Lua 中建立出來,也不能在 Lua 中修改。這樣的操做只能經過 C API。 這一點保證了宿主程序徹底掌管其中的數據。線程

    4. thread 類型用來區別獨立的執行線程,它被用來實現 coroutine (協同例程)。 不要把 Lua 線程跟操做系統的線程搞混。 Lua 能夠在全部的系統上提供對 coroutine 的支持,即便系統並不支持線程。調試

    5. table 類型實現了一個關聯數組。語言自己採用一種語法糖,支持以 a.name 的形式表示 a["name"]。

    6.  特別的,由於函數自己也是值,因此 table 的域中也能夠放函數。 這樣 table 中就能夠有一些 methods 了。

    7. table, function ,thread ,和 (full) userdata 這些類型的值是所謂的對象: 變量自己並不會真正的存放它們的值,而只是放了一個對對象的引用。 賦值,參數傳遞,函數返回,都是對這些對象的引用進行操做; 這些操做不會作暗地裏作任何性質的拷貝。

  4. Boolean 類型只有兩種值:false 和 true。 nil 和 false 都能致使條件爲假;而另外全部的值都被看成真。

  5. Number 表示實數(雙精度浮點數)。

  6. Lua 提供運行時字符串到數字的自動轉換。 

  7. 全局變量,局部變量,還有 table 的域。

  8.  chunk :Lua 的一個執行單元被稱做 chunk。 一個 chunk 就是一串語句段,它們會被循序的執行。 每一個語句段能夠以一個分號結束。lua 把一個 chunk 看成一個擁有不定參數的匿名函數 (參見 §2.5.9)處理。 正是這樣,chunk 內能夠定義局部變量,接收參數,而且返回值。

  9. 賦值:賦值段首先會作運算完全部的表達式,而後僅僅作賦值操做。 所以,下面這段代碼

    1.  i = 3
       i, a[i] = i+1, 20
    2. 會把 a[3] 設置爲 20,而不會影響到 a[4] 。 這是由於 a[i] 中的 i 在被賦值爲 4 以前就被拿出來了(那時是 3 )。 簡單說 ,這樣一行

    3. x, y = y, x
    4. 能夠用來交換 x 和 y 中的值。

  10. for 和 while:

    1. for v = e1, e2, e3 do block end
    2. 用while表達:

    3.     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
               local v = var
               block
               var = var + step
             end
           end
    4. 注意:有個問題,for i=3,2,0 do print(i) end, 會進入死循環。

  11. 可變參數:函數調用和可變參數表達式均可以放在多重返回值中。 若是表達式做爲一個獨立語句段出現 (這隻能是一個函數調用), 它們的返回列表將被對齊到零個元素,也就是忽略全部返回值。 若是表達式用於表達式列表的最後(或者是惟一)的元素, 就不會有任何的對齊操做(除非函數調用用括號括起來)。 在任何其它的狀況下,Lua 將把表達式結果當作單一元素, 忽略除第一個以外的任何值。被括號括起來的表達式永遠被看成一個值。因此, (f(x,y,z)) 即便 f 返回多個值,這個表達式永遠是一個單一值。 ((f(x,y,z)) 的值是 f 返回的第一個值。若是 f 不返回值的話,那麼它的值就是 nil 。)

    1.      f()                    -- 調整到 0 個結果
           g(f(), x)              -- f() 被調整到一個結果
           g(x, f())              -- g 被傳入 x 加上全部 f() 的返回值
           a,b,c = f(), x         -- f() 被調整到一個結果 ( c 在這裏被賦爲 nil )
           a,b = ...              -- a 被賦值爲可變參數中的第一個,
                                      -- b 被賦值爲第二個 (若是可變參數中並無對應的值,
      						-- 這裏 a 和 b 都有可能被賦爲 nil)
           
           a,b,c = x, f()         -- f() 被調整爲兩個結果
           a,b,c = f()            -- f() 被調整爲三個結果
           return f()             -- 返回 f() 返回的全部結果
           return ...             -- 返回全部從可變參數中接收來的值
           return x,y,f()         -- 返回 x, y, 以及全部 f() 的返回值
           {f()}                    -- 用 f() 的全部返回值建立一個列表
           {...}                      -- 用可變參數中的全部值建立一個列表
           {f(), nil}                 -- f() 被調整爲一個結果
  12. 比較操做符:等於操做 (==) 首先比較操做數的類型。 若是類型不一樣,結果就是 false。 不然,繼續比較。 數字和字符串都用常規的方式比較。 對象 (table ,userdata ,thread ,以及函數)以引用的形式比較: 兩個對象只有在它們指向同一個東西時才認爲相等。 每次你建立一個新對象(一個 table 或是 userdata ,thread 函數), 它們都各不相同,即不一樣於上次建立的東西。

  13. andor, 以及 not:and要找一個假的,or要找一個真的,找到就返回;到最後也找不到就返回最後的元素。

    1.      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
  14. 操做符的優先級:寫在下表中,從低到高優先級排序:

    1.      or
           and
           <     >     <=    >=    ~=    ==
           ..
           +     -
           *     /     %
           not   #     - (unary)
           ^
    2. 一般,能夠用括號來改變運算次序。 鏈接操做符 ('..') 和冪操做 ('^') 是從右至左的。 其它全部的操做都是從左至右。下面是一些例子:

    3. print(false or 5 and 6)      			        --> 6
      print(false or 5 and nil)				--> nil
      print(false or 2+3 >= 4*1 and not 7^2)	--> false
      print(false or 2+3 >= 4*1 and not nil)	        --> true
      print(not nil)						--> true
      print(false or nil)					--> nil
  15. 經常使用卻不在乎的元方法:

    1. "lt" 或是 "le":大小比較操做以如下方式進行。 若是參數都是數字,那麼就直接作數字比較。 不然,若是參數都是字符串,就用字符串比較的方式進行。 再則,Lua 就試着調用 "lt" 或是 "le" 元方法 。

    2. concat:字符串的鏈接操做符寫做兩個點 ('..')。 若是兩個操做數都是字符串或都是數字,鏈接操做將以 &sect;2.2.1 中提到的規則把其轉換爲字符串。 不然,會取調用元方法 "concat"。

  16. 取長度操做符:寫做一元操做 #。 字符串的長度是它的字節數(就是以一個字符一個字節計算的字符串長度)。

    table t 的長度被定義成一個整數下標 n 。 它知足 t[n] 不是 nil 而 t[n+1] 爲 nil; 此外,若是 t[1] 爲 nil ,n 就多是零。 對於常規的數組,裏面從 1 到 n 放着一些非空的值的時候, 它的長度就精確的爲 n,即最後一個值的下標。 若是數組有一個「空洞」 (就是說,nil 值被夾在非空值之間), 那麼 #t 多是任何一個是 nil 值的位置的下標 (就是說,任何一個 nil 值都有可能被當成數組的結束)。

  17. 語法糖:

    1. 表:a.name 的形式表示 a["name"];

    2. 函數: v:name(args) 這個樣子,被解釋成 v.name(v,args), 這裏 v 只會被求值一次。

    3. 函數:調用形式 f{fields} 是一種語法糖用於表示 f({fields}); 這裏指參數列表是一個單一的新建立出來的列表;

    4. 函數:形式 f'string' (或是 f"string" 亦或是 f[[string]]) 也是一種語法糖,用於表示 f('string'); 這裏指參數列表是一個單獨的字符串。

    5. 冒號語法能夠用來定義方法, 就是說,函數能夠有一個隱式的形參 self。 所以,以下寫法:

          function t.a.b.c:f (params) body end

    6.     是這樣一種寫法的語法糖:

          t.a.b.c.f = function (self, params) body end

    7. 簡化函數定義:

      1. 這樣的寫法:

         function f () body end

        被轉換成

        f = function () body end

      2. 這樣的寫法:

        function t.a.b.c.f () body end

        被轉換成

         t.a.b.c.f = function () body end

      3. 這樣的寫法:

        local function f () body end

         被轉換成

         local f; f = function () body end

        注意,並非轉換成

         local f = function () body end

        (這個差異只在函數體內須要引用 f 時纔有。)



  18. 尾調用:調用形式:return functioncall 將觸發一個尾調用。 Lua 實現了適當的尾部調用(或是適當的尾遞歸): 在尾調用中, 被調用的函數重用調用它的函數的堆棧項。 所以,對於程序執行的嵌套尾調用的層數是沒有限制的。 然而,尾調用將刪除調用它的函數的任何調試信息。 注意,尾調用只發生在特定的語法下, 這時, return 只有單一函數調用做爲參數; 這種語法使得調用函數的結果能夠精確返回。 所以,下面這些例子都不是尾調用:

    1.      return (f(x))        -- 返回值被調整爲一個
           return 2 * f(x)
           return x, f(x)       -- 最加若干返回值
           f(x); return         -- 無返回值
           return x or f(x)     -- 返回值被調整爲一個
  19. 閉包:一個函數定義是一個可執行的表達式, 執行結果是一個類型爲 function 的值。 當 Lua 預編譯一個 chunk 的時候, chunk 做爲一個函數,整個函數體也就被預編譯了。 那麼,不管什麼時候 Lua 執行了函數定義, 這個函數自己就被實例化了(或者說是關閉了)。 這個函數的實例(或者說是closure(閉包)) 是表達式的最終值。 相同函數的不一樣實例有可能引用不一樣的外部局部變量, 也可能擁有不一樣的環境表。

  20. 形參,實參當一個函數被調用, 若是函數沒有被定義爲接收不定長參數,即在形參列表的末尾註明三個點 ('...'), 那麼實參列表就會被調整到形參列表的長度, 變長參數函數不會調整實參列表; 取而代之的是,它將把全部額外的參數放在一塊兒經過變長參數表達式傳遞給函數, 其寫法依舊是三個點。 這個表達式的值是一串實參值的列表,看起來就跟一個能夠返回多個結果的函數同樣。 若是一個變長參數表達式放在另外一個表達式中使用,或是放在另外一串表達式的中間, 那麼它的返回值就會被調整爲單個值。 若這個表達式放在了一系列表達式的最後一個,就不會作調整了(除非用括號給括了起來)。

    咱們先作以下定義,而後再來看一個例子:

    1.      function f(a, b) end
           function g(a, b, ...) end
           function r() return 1,2,3 end

    下面看看實參到形參數以及可變長參數的映射關係:

    1.      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
  21. 地方

相關文章
相關標籤/搜索