從前幾回的研究中,我已經學會 Lua 的函數宣告,也只是一個 function 變數,以及相關的語法糖
今天我想來探索 Lua 的函數多值回傳特性
這在之前學習迭代函數與迴圈時,就有看到這樣的語法
for _, sFile in ipairs(tApis) do
-- 略 --
end
而主題則是,CC: Tweaked 電腦如何在我輸入的過程中,猜到或預期可能的指令?
如以下畫面
現在我已經知道,shell.lua 有個無窮迴圈,會持續等待玩家的輸入
也就是以下這段程式碼,是我上次暫時沒深入研究的部分
term 的操作,是 /rom/apis/term.lua
看起來這邊只是在設定畫面或文字,所以我也先略過
而 tCommandHistory 看來是紀錄每次玩家的指令
以便可以一直按上下鍵來快速執行之前的指令
-- Read commands and execute them
local tCommandHistory = {}
while not bExit do
term.redirect(parentTerm)
term.setBackgroundColor(bgColour)
term.setTextColour(promptColour)
write(shell.dir() .. "> ")
term.setTextColour(textColour)
local sLine
if settings.get("shell.autocomplete") then
sLine = read(nil, tCommandHistory, shell.complete)
else
sLine = read(nil, tCommandHistory)
end
if sLine:match("%S") and tCommandHistory[#tCommandHistory] ~= sLine then
table.insert(tCommandHistory, sLine)
end
shell.run(sLine)
end
所以關鍵應該是這一行
sLine = read(nil, tCommandHistory, shell.complete)
為了印證我的假設,我直接在「電腦」的硬碟上,新增一個 test2.lua 以及上面這一行,執行結果如下
接下來就有兩個 function 可以持續深入
分別是 read 和 shell.complete
shell.complete 有相對完整的註解說明
很明顯這就是持續接收我的輸入,並猜測我要打的指令了!
-- This accepts an incomplete command, and completes the program name or
-- arguments. For instance, `l` will be completed to `ls`, and `ls ro` will be
-- completed to `ls rom/`.
read 則是在 bios.lua #181
但我只想先專注在多值回傳的部分
function read(_sReplaceChar, _tHistory, _fnComplete, _sDefault)
-- 略 --
local w = term.getSize()
local sx = term.getCursorPos()
-- 重新設定游標位置與輸出字串,若有設定 complete function 則再設定顏色與猜測的指令 --
local function redraw(_bClear)
-- 略 --
local _, cy = term.getCursorPos()
term.setCursorPos(sx, cy)
-- 略 --
if nCompletion then
-- 略 --
end
term.setCursorPos(sx + nPos - nScroll, cy)
end
-- 略 --
end
再參考 /rom/apis/window.lua
顯然這兩個 function 預設是回傳多個值
function window.getSize()
return nWidth, nHeight
end
function window.getCursorPos()
return nCursorX, nCursorY
end
但上述的指令只用一個值來接收
這樣子就會只有取得第一個回傳值,第二個值就自動忽略了
相當於以下的語法,底線就是忽略的意思,這和 Golang 語法特性是相同的
local w, _ = term.getSize()
local sx, _ = term.getCursorPos()
反之,另一行敘述就是只取第二個值,忽略第一個值
local _, cy = term.getCursorPos()
以下是更多的語法特性實驗
function getCursorPos() return 1, 2 end
local x, y, z = getCursorPos()
print(x, y, z) -- 1 2 nil
print(getCursorPos()) -- 1 2
local x, y, z = 6, getCursorPos()
print(x, y, z) -- 6 1 2
print(6, getCursorPos()) -- 6 1 2
local x, y = getCursorPos(), 5
print(x, y) -- 1 5
print(getCursorPos(), 5) -- 1 5
print(getCursorPos() .. '23') -- 123
function getCursorPos() end
local x, y = getCursorPos(), 5, 7
print(x, y) -- nil 5
根據實驗結果可以知道
函數回傳值不夠多的時候,多餘的接收參數都會是 nil
而且函數的多值回傳必須是最後的陳述式,否則只會回傳第一個值
以上是今天的分享與研究心得~