基礎 3:Table 與保護呼叫
table:一個變數裝很多個值
前面的變數一次只能放一個值。table 是 Lua 用來一次裝很多個值的容器,用
大括號 {} 建立:
local t = { 0x10, 0x20, 0x30 }t 現在裝了三個值。用 t[1]、t[2]、t[3] 依序取出第 1、2、3 個——Lua 的
編號從 1 開始,不是從 0 開始,這點跟不少其他程式語言不一樣,剛好相反,第一次
接觸容易搞錯,記住「第一個是 [1]」就好。#t 是 table 的長度,這裡 #t == 3。
之後在跟硬體有關的頁面(I2C 讀寫)會看到 table 的另一種用法:一次 讀寫連續好幾個位元組時,多個位元組就是用一個 table 打包起來的。
0x 開頭的數字
範例裡的 0x10、0x20 是十六進位數字,0x 只是「後面接的是十六進位」的
標記;0x10 就是十進位的 16、0x20 是 32。硬體相關的頁面幾乎都用十六進位,
因為暫存器的位移與內容習慣上都寫成十六進位。
string.format:組出固定格式的文字
string.format("%02X", 32) -- 結果是 "20"%02X 是一個格式代碼:X 代表「印成十六進位、用大寫字母」,02 代表「至少
2 位數,不夠的話前面補 0」。所以數字 32(十六進位是 0x20)印出來就是
"20"——這在印暫存器內容時很常用,保證每個位元組都印成整齊的兩位數。
pcall:保護呼叫,讓錯誤不會中斷腳本
正常情況下,腳本執行途中如果出錯(例如呼叫 error("boom")),腳本會立刻停止。
pcall(函式) 會幫你把這次呼叫包起來:就算裡面出錯,pcall 也只是回報
「這次失敗了」,腳本本身繼續往下跑,不會被中斷。
local ok, err = pcall(function()
error("boom")
end)
-- ok 會是 false(表示失敗了)
-- err 會是錯誤訊息,內容包含 "boom"ok 是 true/false,代表這次呼叫有沒有成功;失敗時 err 會是錯誤訊息。
function() ... end 是一個沒有名字、當場定義、直接丟給 pcall 用一次的函式,
寫法跟上一頁的具名函式一樣,只是省略了名字。
確認錯誤訊息裡有沒有某個字:nil、~=、string.find、tostring
範例最後想再確認一件事:剛剛那次失敗的錯誤訊息裡,真的有出現 "boom" 這個字嗎?
需要認識幾個新東西:
nil:Lua 裡代表「沒有值」、「什麼都沒有」的一個特殊值,不是數字也不是 字串,就是「空」。string.find(文字, 要找的內容):在「文字」裡搜尋「要找的內容」,找得到就回傳 找到的位置(一個數字);找不到就回傳nil。~=:「不等於」,跟上一頁的==(相等)相反。tostring(值):把任何值轉成字串。err這裡大多已經是字串,先轉一次是保險 寫法,就算不是字串也能安全比對。
把這幾個接起來:string.find(tostring(err), "boom") ~= nil 的意思是「把 err
轉成字串後去找 "boom",結果不是 nil」——換句話說,就是「真的找到了」。
範例:table、string.format、pcall 一次看
-- table、string.format("%02X")、pcall 保護呼叫。
local t = { 0x10, 0x20, 0x30 }
check(#t == 3, "table has 3 elements")
local hex = string.format("%02X", t[2])
check(hex == "20", "string.format %02X on 0x20")
local ok, err = pcall(function()
error("boom")
end)
check(ok == false, "pcall caught the error")
check(string.find(tostring(err), "boom") ~= nil, "error message mentions boom")
log("info", "basics_table done")CHECK OK: table has 3 elements
CHECK OK: string.format %02X on 0x20
CHECK OK: pcall caught the error
CHECK OK: error message mentions boom
basics_table done自己跑跑看:
nexus_tui.exe --dongle mock --batch --run basics_table.lua接下來
Lua 的基礎語法到這裡告一段落。下一頁開始進入跟硬體有關的部分:怎麼用腳本讀寫 I2C 暫存器。