Lua 程式設計/表示式
如前所述,表示式是具有值的程式碼片段,可以進行評估。它們不能直接執行(函式呼叫除外),因此,僅包含以下程式碼(由表示式組成)的指令碼將是錯誤的
3 + 5
-- The code above is erroneous because all it contains is an expression.
-- The computer cannot execute '3 + 5', since that does not make sense.
程式碼必須由一系列語句組成。這些語句可以包含表示式,這些表示式將是語句必須操作或用於執行指令的值。
本章中的一些程式碼示例不構成有效的程式碼,因為它們只包含表示式。在下一章中,將介紹語句,並且可以開始編寫有效的程式碼。
評估表示式就是計算它以找到它的值。給定表示式評估到的值可能因上下文而異,因為它可能取決於環境和堆疊級別。這個值有時將是一個數字,有時是文字,有時是許多其他資料型別中的任何一個,這就是為什麼它被稱為具有型別。
在 Lua 中,以及在一般的程式設計中,表示式通常由一個或多個值和零個或多個運算子組成。某些運算子只能與某些型別一起使用(例如,試圖除文字是不合邏輯的,而除數字則有意義)。運算子有兩種:一元運算子和二元運算子。一元運算子是隻接受一個值的運算子。例如,一元運算子 - 只接受一個數字作為引數:-5、-3、-6 等。它接受一個數字作為引數並對該數字取反。然而,二元運算子 - 與之不同,它接受兩個值並將第二個值從第一個值中減去:5 - 3、8 - 6、4 - 9 等。
可以使用 type 函式以字串形式獲取數字的型別
print(type(32425)) --> number
數字通常代表數量,但它們可以用於許多其他用途。Lua 中的數字型別在大多數情況下與實數相同。數字可以構造為整數、小數、小數指數,甚至以 十六進位制 形式。以下是一些有效的數字
- 3
- 3.0
- 3.1416
- 314.16e-2
- 0.31416E1
- 0xff
- 0x56
Lua 中的數字運算子如下
| 操作 | 語法 | 描述 | 示例 | 結果 |
|---|---|---|---|---|
| 算術否定 | -a | 更改 a 的符號並返回該值 | -3.14159 | |
| 加法 | a + b | 返回 a 和 b 的總和 | 5.2 + 3.6 | 8.8 |
| 減法 | a - b | 從 a 中減去 b 並返回結果 | 6.7 - 1.2 | 5.5 |
| 乘法 | a * b | 返回 a 和 b 的乘積 | 3.2 * 1.5 | 4.8 |
| 指數運算 | a ^ b | 返回 a 的 b 次方,或 a 被 b 乘方的結果 | 5 ^ 2 | 25 |
| 除法 | a / b | 用 b 除以 a 並返回結果 | 6.4 / 2 | 3.2 |
| 向下取整除法 | a // b | 用 b 除以 a 並返回結果的整數部分 | 6.4 // 2 | 3 |
| 模運算 | a % b | 返回 a 被 b 除的餘數 | 5 % 3 | 2 |
您可能已經知道所有這些運算子(它們與基本數學運算子相同),除了最後一個。最後一個稱為模運算子,它簡單地計算一個數字被另一個數字除的餘數。例如,5 % 3 將返回 2 作為結果,因為 2 是 5 被 3 除的餘數。模運算子不像其他運算子那麼常見,但它有許多用途。
在 Lua 5.3 中添加了數字的一個新子型別:整數。數字可以是整數或浮點數。浮點數類似於上面描述的數字,而整數是沒有任何小數部分的數字。浮點數除法 (/) 和指數運算始終將其運算元轉換為浮點數,而所有其他運算子如果其兩個運算元都是整數,則返回整數。在其他情況下,除了向下取整除法運算子 (//) 之外,結果將是浮點數。
Nil 是值 nil 的型別,其主要屬性是與任何其他值不同;它通常表示缺少有用的值。以下是一些具有 nil 值的事物的示例
- 您在為變數分配值之前訪問它們的變數的值
- 嘗試在變數作用域之外訪問變數時得到的值
- 表中任何未分配的鍵的值
tonumber返回的值,如果它無法將字串轉換為數字
更高階一點,有意分配 nil 值會刪除對變數或表的引用,並允許 垃圾收集器 重新分配其記憶體。
布林值可以是 true 或 false,但不能是其他值。在 Lua 中,它寫為 true 和 false,它們是保留關鍵字。重要的是要注意 nil 是一個不同的資料型別,如前所述。and、or、not() 通常與布林值相關聯,但可以在 Lua 中與任何資料型別一起使用。
| 操作 | 語法 | 描述 |
|---|---|---|
| 布林值否定 | not a | 如果 a 為 false 或 nil,則返回 true。否則,返回 false。 |
| 邏輯連線 | a and b | 如果第一個引數為 false 或 nil,則返回第一個引數。否則,返回第二個引數。 |
| 邏輯析取 | a or b | 如果第一個引數既不是 false 也不是 nil,則返回第一個引數。否則,返回第二個引數。 |
本質上,not 運算子只是對布林值取反(如果它是 true 則使其變為 false,如果它是 false 則使其變為 true),and 運算子如果兩者都為 true 則返回 true,否則返回 false,而 or 運算子如果其中任何一個引數為 true 則返回 true,否則返回 false。然而,這並不是它們的工作原理,因為它們的實際工作原理如上表所述。在 Lua 中,值 false 和 nil 在邏輯表示式中都被視為 false,而其他所有內容都被視為 true(即使是 0 和空字串)。
下一章中介紹的關係運算符 (<、>、<=、>=、~=、==) 不一定將布林值作為運算元,但始終會返回布林值作為結果。
這可能難以理解。為了更清楚地說明,以下是一些真值表或表示式-結果對。這裡 x 可以是 nil、true 或 false
| 表示式 | 結果 |
|---|---|
true and x
|
x
|
false and x
|
false
|
nil and x
|
nil
|
true or x
|
true
|
false or x
|
x
|
nil or x
|
x
|
這有點違反直覺,這意味著
| 表示式 | 結果 |
|---|---|
false and nil
|
false
|
nil and false
|
nil
|
此外,
| 表示式 | 結果 |
|---|---|
false == nilnil == false
|
false
|
nil and false
|
nil
|
| 表示式 | 結果 |
|---|---|
not(false)not(nil)
|
true
|
not(true)
|
false
|
字串是字元的序列,可以用來表示文字。它們可以在 Lua 中用雙引號、單引號或長括號表示,這些在之前的關於註釋的部分中已經介紹過(需要注意的是,註釋和字串除了都可以用長括號分隔之外,沒有其他共同點,註釋需要在長括號前面加上兩個連字元)。沒有用長括號括起來的字串只持續一行。因此,要建立一個包含多行的字串而不用長括號,唯一的方法是使用轉義序列。這也是在某些情況下插入單引號或雙引號的唯一方法。轉義序列由兩部分組成:跳脫字元,在 Lua 中總是反斜槓 ('\'),以及一個標識要轉義的字元的識別符號。
| 轉義序列 | 描述 |
|---|---|
| \n | 換行符 |
| \" | 雙引號 |
| \' | 單引號(或撇號) |
| \\ | 反斜槓 |
| \t | 水平製表符 |
| \### | ### 必須是一個從 0 到 255 的數字。結果將是對應的ASCII字元。 |
當直接將字元放入字串會導致問題時,會使用轉義序列。例如,如果一個字串包含在雙引號中,並且必須包含雙引號,那麼就需要將字串包含在不同的字元中,或者對雙引號進行轉義。在用長括號分隔的字串中跳脫字元是不必要的,這對所有字元都適用。用長括號分隔的字串中的所有字元都將按原樣處理。% 字元在字串模式中用於轉義魔法字元,但術語轉義在另一種情況下使用。
"This is a valid string."
'This is also a valid string.'
"This is a valid \" string 'that contains unescaped single quotes and escaped double quotes."
[[
This is a line that can continue
on more than one line.
It can contain single quotes, double quotes and everything else (-- including comments). It ignores everything (including escape characters) except closing long brackets of the same level as the opening long bracket.
]]
"This is a valid string that contains tabs \t, double quotes \" and backlashes \\"
"This is " not a valid string because there is an unescaped double quote in the middle of it."
為了方便起見,如果一個開始的長字串括號緊跟著一個換行符,那麼這個換行符將被忽略。因此,以下兩個字串是等價的
[[This is a string
that can continue on many lines.]]
[[
This is a string
that can continue on many lines.]]
-- Since the opening long bracket of the second string is immediately followed by a new line, that new line is ignored.
可以使用一元長度運算子 ('#') 獲取字串的長度,以數字形式表示
print(#("This is a string")) --> 16
連線
[edit | edit source]—維基百科, 連線
Lua 中的字串連線運算子用兩個點 ('..') 表示。下面是一個連線 "snow" 和 "ball" 並列印結果的例子
print("snow" .. "ball") --> snowball
這段程式碼將連線 "snow" 和 "ball" 並列印結果。
其他型別
[edit | edit source]Lua 中的四種基本型別(數字、布林值、nil 和字串)已經在之前的部分中介紹過,但還有四種類型沒有介紹:函式、表、userdata 和執行緒。函式是可以呼叫的程式碼片段,可以接收值並返回結果。表是可以用於資料操作的資料結構。userdata是在 Lua 嵌入的應用程式內部使用的,用於允許 Lua 透過應用程式控制的物件與該程式進行通訊。最後,執行緒由協程使用,協程允許多個函式同時執行。這些將在後面介紹,所以只需要記住還有其他的資料型別。
字面量
[edit | edit source]字面量是在原始碼中表示固定值的表示法。除了執行緒和 userdata 之外,所有值都可以用字面量在 Lua 中表示。字串字面量(計算結果為字串的字面量)例如,由字串必須表示的文字組成,這些文字包含在單引號、雙引號或長括號中。另一方面,數字字面量由它們用十進位制表示法(例如:12.43)、科學計數法(例如:3.1416e-2 和 0.31416E1)或十六進位制表示法(例如:0xff)表示的數字組成。
強制轉換
[edit | edit source]強制轉換是指將一種資料型別的值轉換為另一種資料型別的值。Lua 在字串和數字值之間提供了自動強制轉換。對字串應用的任何算術運算都將嘗試將該字串轉換為數字。相反,只要需要字串而使用的是數字,數字就會被轉換為字串。這適用於 Lua 運算子和預設函式(與語言一起提供的函式)。
print("122" + 1) --> 123
print("The number is " .. 5 .. ".") --> The number is 5.
數字到字串和字串到數字的強制轉換也可以使用 tostring 和 tonumber 函式手動完成。前者接受一個數字作為引數並將其轉換為字串,而後者接受一個字串作為引數並將其轉換為數字(可以在第二個引數中選擇一個與預設十進位制不同的基數)。
位運算
[edit | edit source]從 Lua 5.3 開始,提供了位運算子來對二進位制數字(位模式)進行運算。這些運算子不像其他運算子那樣經常使用,所以如果你不需要它們,可以跳過這一節。
Lua 中的位運算子始終對整數進行運算,如果需要會將運算元轉換為整數。它們也返回整數。
按位與運算(運算子為 &)對兩個二進位制表示形式的相同長度的每對位執行邏輯合取。例如,5 & 3 計算結果為 1。我們可以透過檢視這些數字的二進位制表示來解釋這一點(下標用於表示基數)
如果 5 和 3 的二進位制表示中給定位置上的位都是 1(例如,最後一位),那麼結果中該位置上的位將是 1;在所有其他情況下,它將是 0。
按位或運算(運算子為 |)的工作原理與按位與相同,只是它在執行邏輯合取的地方執行邏輯析取。因此,5 | 3 將計算結果為 7
在這裡,我們可以看到,只有當兩個運算元的二進位制表示在該位置上都為 0 位時,最終結果中該位置上的位才為 0。
按位異或運算(運算子為 ~)的工作原理與其他兩個運算子類似,但在給定位置上,只有當一個運算元的位為 1,而另一個運算元的位不為 1 時,最終位才為 1。
這與前面的例子相同,但我們可以看到結果中的最後一位是 0 而不是 1,因為兩個運算元的最後一位都是 1。
按位取反運算(運算子為 ~)對唯一運算元的每一位執行邏輯否定,這意味著每個 0 都變成 1,每個 1 都變成 0。因此,~7 將計算結果為 -8
這裡,第一個位在結果中變為 1 是因為在運算元中它是 0,其他位變為 0 是因為它們都是 1。
除了這些按位運算子之外,Lua 5.3 還支援算術位移。左側的左移,運算子為<<,左側的說明是將所有位向左移動,移動的位數與第二個運算元對應。右側的右移,運算子為>>,右側的說明是相同方向的反向操作。
運算子優先順序在 Lua 中的工作方式與在數學中通常相同。某些運算子將在其他運算子之前計算,並且可以使用括號任意更改執行運算的順序。運算子計算的優先順序在下面的列表中,從最高優先順序到最低優先順序。其中一些運算子尚未討論,但它們都將在本書的某個時間點介紹。
- 指數運算:
^ - 一元運算子:
not,#,-,~ - 2 級數學運算子:
*,/,//,% - 1 級數學運算子:
+,- - 連線:
.. - 位移:
<<,>> - 按位 AND:
& - 按位 XOR:
~ - 按位 OR:
| - 關係運算符:
<,>,<=,>=,~=,== - 布林 AND:
and - 布林 OR:
or
您可以回答一些問題,以驗證您是否理解本章中的內容。請注意,找到某些問題的答案可能需要您擁有本章中未介紹的知識。這是正常的:測驗是學習體驗的一部分,它們可以介紹書中其他地方沒有的資訊。