無標題文章te

本文所有內(nèi)容全部都是我在閱讀了《Programming in Lua》這本書之后整理出來的,可以理解本文為一個快速查詢的“手冊”,因此并不適合零基礎的讀者。入門學習的話,還是建議先看看《Programming in Lua》這本書。本文并未包含所有的Lua語法,并不是Lua語法大全。很多高級特性,相信在你用到的時候,以下內(nèi)容肯定都已經(jīng)了然于心了,不再需要這種入門級的小手冊了。
另外,今天是愚人節(jié)!但是我并不想騙你們!以下內(nèi)容并不是愚人節(jié)的禮物,如果踩到坑,恕我無心。

關于Lua語言的一些基本常識

  • Chunk 是一系列語句,Lua 執(zhí)行的每一塊語句,比如一個文件或者交互模式下的每一行都是一個 Chunk。一個 Chunk 可以是一個語句,也可以是一系列語句的組合,還可以是函數(shù),Chunk可以很大,在 Lua 中幾個 MByte 的 Chunk 是很常見的。
  • 每個語句結(jié)尾的分號(;)是可選的,但如果同一行有多個語句最好用;分開
  • 命令lua -la -lb首先在一個 Chunk 內(nèi)先運行 a 然后運行 b。(注意:-l 選項會調(diào)用 require,將會在指定的目錄下搜索文件,如果環(huán)境變量沒有設好,上面的命令可能不能正確運行。)
  • lua -i -la -lb,-i 選項要求 Lua 運行指定 Chunk 后進入交互模式.
  • dofile 函數(shù)加載文件并執(zhí)行它
  • 全局變量不需要聲明,給一個變量賦值后即創(chuàng)建了這個全局變量,訪問一個沒有初始化的全局變量也不會出錯,只不過得到的結(jié)果是:nil.當且僅當一個變量不等于 nil 時,這個變量存在。
  • Lua 是大小寫敏感的.
  • 單行注釋:-- 注釋內(nèi)容
  • 多行注釋:--[[ 注釋內(nèi)容,這里可以有多行。 --]]
  • 可以直接通過命令參數(shù)傳入Lua語句。prompt> lua -e "print(math.sin(12))" --> -0.53657291800043 -e:直接將命令傳入 Lua
  • 全局變量 arg 存放 Lua 的命令行參數(shù)。

類型和值

  • Lua 是動態(tài)類型語言,變量不要類型定義。 Lua 中有 8 個基本類型分別為: nil、boolean、number、string、userdata、function、thread 和 table。函數(shù) type 可以測試給定變量或者值的類型。
  • 關于布爾值需要注意:Lua 中所有的值都可以作為布爾值來用。在控制結(jié)構(gòu)的條件中除了 false 和 nil 為假,其他值都為真。Lua 認為 0 和空串都是真。
  • 可以使用單引號或者雙引號表示字符串
  • 除了雙引號和單引號,還可以使用[[...]]表示字符串。這種形式的字符串可以包含多行,可以嵌套且不會解釋轉(zhuǎn)義序列,如果第一個字符是換行符會被自動忽略掉。這種形式的字符串用來包含一段代碼是非常方便的。
  • 運行時,Lua 會自動在 string 和 numbers 之間自動進行類型轉(zhuǎn)換,當一個字符串使用算術(shù)操作符時,string 就會被轉(zhuǎn)成數(shù)字。反過來,當 Lua 期望一個 string 而碰到數(shù)字時,會將數(shù)字轉(zhuǎn)成 string。
  • ..在 Lua 中是字符串連接符,當在一個數(shù)字后面寫..時,必須加上空格以防止被解釋錯。print(10 .. 20) --> 1020

表達式和運算符

  • Lua中不等號是~=
  • 如果兩個值類型不同,Lua 認為兩者不同;nil 只和自己相等。Lua 通過引用比較 tables、userdata、functions。也就是說當且僅當兩者表示同一個對象時相等。
  • Lua 比較數(shù)字按傳統(tǒng)的數(shù)字大小進行,比較字符串按字母的順序進行,但是字母順序依賴于本地環(huán)境。
  • Lua的邏輯運算符是 and or not
  • list 風格初始化和 record 風格初始化是[expression]一般初始化的特例
  • Lua數(shù)組下標從1開始

基本語法

  • Lua 可以對多個變量同時賦值,變量列表和值列表的各個元素用逗號分開,賦值語句右邊的值會依次賦給左邊的變量。a,b = 10, 2x <--> a=10; b=2x。多值賦值經(jīng)常用來交換變量,或?qū)⒑瘮?shù)調(diào)用返回給變量:a, b = f()
  • 遇到賦值語句 Lua 會先計算右邊所有的值然后再執(zhí)行賦值操作,所以我們可以這樣進行交換變量的值:x, y = y, x。變量個數(shù) > 值的個數(shù) 按變量個數(shù)補足 nil,變量個數(shù) < 值的個數(shù) 多余的值會被忽略。
  • 使用local 創(chuàng)建一個局部變量,與全局變量不同,局部變量只在被聲明的那個代碼塊內(nèi)有效。代碼塊:指一個控制結(jié)構(gòu)內(nèi),一個函數(shù)體,或者一個 chunk(變量被聲明的那個文件或者文本串)。
  • do..end(相當于 c/c++的{})

流程控制語句

條件

if conditions then
    print("hello elvin!");
end;

if conditions then
    print("hello elvin!");
else
    print("hello elvin!");
end;

if conditions then
    print("hello elvin!");
elseif conditions then
    print("hello elvin!");
    -- 多個elseif
else
    print("hello elvin!");
end

循環(huán)

while 語句
while condition do
    print("hello elvin!");
end;
repeat-until 語句
repeat
    print("hello elvin!");
until conditions;
for 語句

for 語句有兩大類

第一類,數(shù)值for循環(huán)
for var=exp1,exp2,exp3 do
    loop-part
end

for 將用 exp3 作為 step 從 exp1(初始值)到 exp2(終止值),執(zhí)行 loop-part。其中exp3可以省略,默認step=1。
有幾點需要注意:

  1. 三個表達式只會被計算一次,并且是在循環(huán)開始前。
for i=1,f(x) do
    print(i)
end
for i=10,1,-1 do
    print(i)
end

第一個例子 f(x)只會在循環(huán)前被調(diào)用一次。

  1. 控制變量 var 是局部變量自動被聲明,并且只在循環(huán)內(nèi)有效.
for i=1,10 do
    print(i)
end
max = i
-- probably wrong! 'i' here is global

如果需要保留控制變量的值,需要在循環(huán)中將其保存

-- find a value in a list
local found = nil
for i=1,a.n do
    if a[i] == value then
        found = i
        -- save value of 'i'
        break
    end
end
print(found)
  1. 循環(huán)過程中不要改變控制變量的值,那樣做的結(jié)果是不可預知的。
    如果要退出循環(huán),使用 break 語句。
第二類,范型for循環(huán)

前面已經(jīng)見過一個例子:

-- print all values of array 'a'
for i,v in ipairs(a) do
    print(v)
end

范型 for 遍歷迭代子函數(shù)返回的每一個值。再看一個遍歷表 key 的例子:

-- print all keys of table 't'
for k in pairs(t) do
    print(k)
end

范型 for 和數(shù)值 for 有兩點相同:

  1. 控制變量是局部變量
  2. 不要修改控制變量的值

再看一個例子,假定有一個表:

days = {"Sunday", "Monday", "Tuesday", "Wednesday","Thursday", "Friday", "Saturday"}

現(xiàn)在想把對應的名字轉(zhuǎn)換成星期幾,一個有效地解決問題的方式是構(gòu)造一個反向表:

revDays = {
  ["Sunday"] = 1,
  ["Monday"] = 2,
  ["Tuesday"] = 3,
  ["Wednesday"] = 4,
  ["Thursday"] = 5,
  ["Friday"] = 6,
  ["Saturday"] = 7
}

下面就可以很容易獲取問題的答案了:

x = "Tuesday"
print(revDays[x])
--> 3

其實,我們不需要手工做這件事情,可以自動構(gòu)造反向表。

revDays = {}
for i,v in ipairs(days) do
    revDays[v] = i
end

Lua 語法要求break和return只能出現(xiàn)在block的結(jié)尾一句(也就是說:作為 chunk的最后一句,或者在end之前,或者else前,或者until前),有時候為了調(diào)試或者其他目的需要在block的中間使用return或者break,可以顯式的使用do..end來實現(xiàn):

do return end

函數(shù)

  1. 函數(shù)定義語法
function func_name(arguments-list)
    statements-list;
end;
  1. 調(diào)用函數(shù)的時候,如果參數(shù)列表為空,必須使用()表明是函數(shù)調(diào)用。上述規(guī)則有一個例外,當函數(shù)只有一個參數(shù)并且這個參數(shù)是字符串或者表構(gòu)造的時候,()可有可無:
print "Hello World" -- -> print("Hello World")
dofile 'a.lua' -- -> dofile ('a.lua')
f{x=10, y=20} -- -> f({x=10, y=20})
type{} -- -> type({})
  1. Lua 函數(shù)實參和形參的匹配與賦值語句類似,多余部分被忽略,缺少部分用 nil 補足。

  2. Lua 函數(shù)可以接受可變數(shù)目的參數(shù),和 C 語言類似在函數(shù)參數(shù)列表中使用三點(...)表示函數(shù)有可變的參數(shù)。Lua 將函數(shù)的參數(shù)放在一個叫 arg 的表中,除了參數(shù)以外,arg表中還有一個域 n 表示參數(shù)的個數(shù)。

  3. 如果我們只想要 string.find 返回的第二個值。一個典型的方法是使用啞元(dummy variable,下劃線):

local _, x = string.find(s, p)
  1. 使用圓括號強制使調(diào)用返回一個值。
print((foo0()))
-- 將只打印foo0的第一個返回值。
  1. Lua中定義方法的另一種特殊方式
Lib = {}
function Lib.foo (x,y)
return x + y
end
  1. 當我們將函數(shù)保存在一個局部變量內(nèi)時,我們得到一個局部函數(shù),也就是說局部函數(shù)像局部變量一樣在一定范圍內(nèi)有效。

    • 方式一

      local f = function (...)
      
      end
      local g = function (...)
          f()
          -- external local `f' is visible here
      end
      
    • 方式二

      local function f (...)
      
      end
      
  2. 在定義非直接遞歸局部函數(shù)時要先聲明然后定義才可以

環(huán)境

Lua 用一個名為 environment 普通的表來保存所有的全局變量。
Lua 將環(huán)境本身存儲在一個全局變量_G 中,(_G._G 等于_G)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容