Skip to Content
Lua 自動化基礎 3:Table 與保護呼叫

基礎 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 一次看

basics_table.lua下載 basics_table.lua
-- 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 暫存器。