Lua 編程

Lua 編程

經典的"Hello world"的程序總是被用來開始介紹一種語言。在Lua中,寫一個這樣的程序很簡單:

  1. print("Hello world")

在Lua中,語句之間可以用分號""隔開,也可以用空白隔開。一般來說,如果多個語句寫在同一行的話,建議總是用分號隔開。 
Lua 有好幾種程序控制語句,如: 
條件控制: if 條件 then … elseif 條件 then … else … end 
While循環: while 條件 do … end 
Repeat循環: repeat … until 條件 
For循環: for 變量 = 初值,終點值,步進 do … end 
For循環: for 變量1,變量2,… ,變量N in表或枚舉函數 do … end

注意一下,for的循環變量總是隻作用於for的局部變量,你也可以省略步進值,這時候,for循環會使用1作爲步進值。 
你可以用break來中止一個循環。

如果你有程序設計的基礎,比如你學過Basic,C之類的,你會覺得Lua也不難。但Lua有幾個地方是明顯不同於這些程序設計語言的,所以請特別注意。

語句塊

語句塊在C++中是用"{"和"}"括起來的,在Lua中,它是用do 和 end 括起來的。比如:

  1. do print("Hello") end

你可以在 函數 中和 語句塊 中定局部變量。

賦值語句

賦值語句在Lua被強化了。它可以同時給多個變量賦值。 
例如:

  1. a,b,c,d=1,2,3,4

甚至是:

  1. a,b=b,a -- 多麼方便的交換變量功能啊。

在默認情況下,變量總是認爲是全局的。假如你要定義局部變量,則在第一次賦值的時候,需要用local說明。比如:

  1. local a,b,c = 1,2,3 -- a,b,c都是局部變量

數值運算

和C語言一樣,支持+, -, *, /。但Lua還多了一個"^"。這表示指數乘方運算。比如2^3 結果爲8, 2^4結果爲16。 
連接兩個字符串,可以用".."運處符。如:

  1. "This a " .. "string." -- 等於 "this a string"

比較運算

< > <= >= == ~= 
分別表示 小於,大於,不大於,不小於,相等,不相等 
所有這些操作符總是返回 true 或 false。 
對於Table,Function和Userdata類型的數據,只有 == 和 ~=可以用。相等表示兩個變量引用的是同一個數據。比如:

  1. a={1,2}
  2. b=a
  3. print(a==b, a~=b) -- true, false
  4. a={1,2}
  5. b={1,2}
  6. print(a==b, a~=b) -- false, true

邏輯運算

and, or, not

其中,and 和 or 與C語言區別特別大。 
在這裏,請先記住,在Lua中,只有 false 和 nil 才計算爲 false,其它任何數據都計算爲 true0 也是 true! 
and 和 or 的運算結果不是 true和false,而是和它的兩個操作數相關。 
a and b: 如果a爲false,則返回a;否則返回b 
a or b: 如果 a 爲true,則返回a;否則返回b 
舉幾個例子:

  1. print(4 and 5) --> 5
  2. print(nil and 13) --> nil
  3. print(false and 13) --> false
  4. print(4 or 5) --> 4
  5. print(false or 5) --> 5

在Lua中這是很有用的特性,也是比較令人混洧的特性。 
我們可以模擬C語言中的語句:

  1. x = a? b : c

在Lua中,可以寫成:

  1. x = a and b or c

最有用的語句是:

  1. x = x or v

它相當於:

  1. if not x then x = v end

運算符優先級

從高到低順序如下:

  1. ^
  2. not - (一元運算)
  3. * /
  4. + -
  5. ..(字符串連接)
  6. < > <= >= ~= ==
  7. and
  8. or

關鍵字

關鍵字是不能做爲變量的。Lua的關鍵字不多,就以下幾個:

  1. and break do else elseif
  2. end false for function if
  3. in local nil not or
  4. repeat return then true until while

變量類型

怎麼確定一個變量是什麼類型的呢?大家可以用type()函數來檢查。Lua支持的類型有以下幾種:

Nil 空值

所有沒有使用過的變量,都是nil。nil既是值,又是類型。

Boolean 布爾值

true 或 false

Number 數值

在Lua裏,數值相當於C語言的double

String 字符串

如果你願意的話,字符串是可以包含'\0'字符的

Table 關係表類型

這個類型功能比較強大,我們在後面慢慢說。

Function 函數類型

不要懷疑,函數也是一種類型,也就是說,所有的函數,它本身就是一個變量。

Userdata

嗯,這個類型專門用來和Lua的宿主打交道的。宿主通常是用C和C++來編寫的,在這種情況下,Userdata可以是宿主的任意數據類型,常用的有Struct和指針。

Thread 線程類型

在Lua中沒有真正的線程。Lua中可以將一個函數分成幾部份運行。如果感興趣的話,可以去看看Lua的文檔。

變量的定義

所有的語言,都要用到變量。在Lua中,不管你在什麼地方使用變量,都不需要聲明,並且所有的這些變量總是全局變量,除非,你在前面加上"local"。 
這一點要特別注意,因爲你可能想在函數裏使用局部變量,卻忘了用local來說明。 
至於變量名字,它是大小寫相關的。也就是說,A和a是兩個不同的變量。 
定義一個變量的方法就是賦值。""操作就是用來賦值的 
我們一起來定義幾種常用類型的變量吧。

Nil

正如前面所說的,沒有使用過的變量的值,都是Nil。有時候我們也需要將一個變量清除,這時候,我們可以直接給變量賦以nil值。如:

  1. var1=nil -- 請注意 nil 一定要小寫

Boolean

布爾值通常是用在進行條件判斷的時候。 
布爾值有兩種:true 和 false。在Lua中,只有false和nil才被計算爲false,而所有任何其它類型的值,都是true。比如0,空串等等,都是true。不要被C語言的習慣所誤導,0在Lua中的的確確是true。你也可以直接給一個變量賦以Boolean類型的值,如:

  1.     varboolean = true

Number

在Lua中,是沒有整數類型的,也不需要。一般情況下,只要數值不是很大(比如不超過100,000,000,000,000),是不會產生舍入誤差的。在很多CPU上,實數的運算並不比整數慢。 
實數的表示方法,同C語言類似,如: 
4 0.4 4.57e-3 0.3e12 5e+20

String

字符串,總是一種非常常用的高級類型。在Lua中,你可以非常方便的定義很長很長的字符串。 
字符串在Lua中有幾種方法來表示,最通用的方法,是用雙引號或單引號來括起一個字符串的,如:

  1. "This is a string."

和C語言相同的,它支持一些轉義字符,列表如下:

  1. \a bell
  2. \b back space
  3. \f form feed
  4. \n newline
  5. \r carriage return
  6. \t horizontal tab
  7. \v vertical tab
  8. \\ backslash
  9. \" double quote
  10. \' single quote
  11. \[ left square bracket
  12. \] right square bracket

由於這種字符串只能寫在一行中,因此,不可避免的要用到轉義字符。加入了轉義字符的串,看起來實在是不敢恭維,比如:

  1.     "one line\nnext line\n\"in quotes\", 'in quotes'"

一大堆的"\"符號讓人看起來很倒胃口。如果你與我有同感,那麼,我們在Lua中,可以用另一種表示方法:用"[["和"]]"將多行的字符串括起來,如:

  1. page = [[
  2. <HTML>
  3.    <HEAD>
  4.      <TITLE>An HTML Page</TITLE>
  5.    </HEAD>
  6.    <BODY>
  7.      <A HREF="http://www.lua.org">Lua</A>
  8.      [[a text between double brackets]]
  9.    </BODY>
  10.  </HTML>
  11.  ]]

值得注意的是,在這種字符串中,如果含有單獨使用的"[["或"]]"就仍然得用"\["或"\]"來避免歧義。當然,這種情況是極少會發生的。

Table

關係表類型,這是一個很強大的類型。我們可以把這個類型看作是一個數組。只是C語言的數組,只能用正整數來作索引;在Lua中,你可以用任意類型來作數組的索引,除了nil。同樣,在C語言中,數組的內容只允許一種類型;在Lua中,你也可以用任意類型的值來作數組的內容,除了nil。

Table的定義很簡單,它的主要特徵是用"{"和"}"來括起一系列數據元素的。比如:

  1. T1 = {} -- 定義一個空表
  2. T1[1]=10 -- 然後我們就可以象C語言一樣來使用它了。
  3. T1["John"]={Age=27, Gender="Male"}

這一句相當於:

  1. T1["John"]={} -- 必須先定義成一個表,還記得未定義的變量是nil類型嗎
  2. T1["John"]["Age"]=27
  3. T1["John"]["Gender"]="Male"

當表的索引是字符串的時候,我們可以簡寫成:

  1. T1.John={}
  2. T1.John.Age=27
  3. T1.John.Gender="Male"

  1. T1.John{Age=27, Gender="Male"}

這是一個很強的特性。 
在定義表的時候,我們可以把所有的數據內容一起寫在"{"和"}"之間,這樣子是非常方便,而且很好看。比如,前面的T1的定義,我們可以這麼寫:

  1. T1=
  2.   {
  3.     10, -- 相當於 [1] = 10
  4.    [100] = 40,
  5.       John= -- 如果你原意,你還可以寫成:["John"] =
  6.       {
  7.         Age=27, -- 如果你原意,你還可以寫成:["Age"] =27
  8.         Gender=Male -- 如果你原意,你還可以寫成:["Gender"] =Male
  9.       },
  10.       20 -- 相當於 [2] = 20
  11. }

看起來很漂亮,不是嗎?我們在寫的時候,需要注意三點: 
第一,所有元素之間,總是用逗號""隔開; 
第二,所有索引值都需要用"["和"]"括起來;如果是字符串,還可以去掉引號和中括號; 
第三,如果不寫索引,則索引就會被認爲是數字,並按順序自動從1往後編; 
表類型的構造是如此的方便,以致於常常被人用來代替配置文件。是的,不用懷疑,它比ini文件要漂亮,並且強大的多。

Function

函數,在Lua中,函數的定義也很簡單。典型的定義如下:

  1. function add(a,b) -- add 是函數名字,ab是參數名字
  2. return a+b -- return 用來返回函數的運行結果
  3. end

請注意,return語言一定要寫在end之前。假如你非要在中間放上一句return,那麼請寫成:do return end。 
還記得前面說過,函數也是變量類型嗎?上面的函數定義,其實相當於:

  1. add = function (a,b) return a+b end

當你重新給add賦值時,它就不再表示這個函數了。你甚至可以賦給add任意數據,包括nil (這樣,你就清除了add變量)。Function是不是很象C語言的函數指針呢? 
和C語言一樣,Lua的函數可以接受可變參數個數,它同樣是用"…"來定義的,比如:

  1. function sum (a,b,…)

如果想取得…所代表的參數,可以在函數中訪問arg局部變量(表類型)得到。如

  1. sum(1,2,3,4)

則,在函數中,

  1. a = 1, b = 2, arg = {3, 4}

更可貴的是,它可以同時返回多個結果,比如:

  1. function s()
  2.   return 1,2,3,4
  3. end
  4. a,b,c,d = s() -- 此時,a = 1, b = 2, c = 3, d = 4

前面說過,表類型可以擁有任意類型的值,包括函數!因此,有一個很強大的特性是,擁有函數的表,哦,我想更恰當的應該說是對象吧。Lua可以使用面向對象編程了。不信?那我舉例如下:

  1.     t =
  2.     {
  3.      Age = 27
  4.      add = function(self, n) self.Age = self.Age+n end
  5.     }
  6.     print(t.Age) -- 27
  7.     t.add(t, 10)
  8.     print(t.Age) -- 37

不過,t.add(t,10) 這一句實在是有點土對吧?沒關係,在Lua中,你可以簡寫成:

  1. t:add(10) -- 相當於 t.add(t,10)

注意事項 
用觸動精靈開發腳本時,一定要記得把封裝函數寫在調用前面,因爲腳本是按照從上往下的順序執行的,如果先調用而沒有封裝,就會報錯。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章