Day11 为什麽电脑能自动完成指令 - Lua 的多值回传

从前几回的研究中,我已经学会 Lua 的函数宣告,也只是一个 function 变数,以及相关的语法糖
今天我想来探索 Lua 的函数多值回传特性
这在之前学习迭代函数与回圈时,就有看到这样的语法

for _, sFile in ipairs(tApis) do
    -- 略 --
end

而主题则是,CC: Tweaked 电脑如何在我输入的过程中,猜到或预期可能的指令?
如以下画面
CC: Tweaked Computer Auto-Complete

现在我已经知道,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 以及上面这一行,执行结果如下
CC: Tweaked Computer Auto-Complete

接下来就有两个 function 可以持续深入
分别是 readshell.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/`.

Lua 函数的多值回传

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
而且函数的多值回传必须是最後的陈述式,否则只会回传第一个值

以上是今天的分享与研究心得~


<<:  Day11-动态元件

>>:  Day 11 利用 docker 安装 nginx 并配置 https

Day17:关於 WS 的使用

前言 这两天因为卡文,所以笔记的部分变得很凌乱和断续,所以之後会再将前面的系列笔记重新调整成第二版,...

Day 06 - 私有云VPC设置

今天我们来研究看看私有云VPC吧 VPC的价值: 懂得如何运用VPC,提供我们一套更好的安全机制,来...

Day 05 - 了解FOREIGN KEY 外键限制!

上一篇在创造新的资料库时,有提到PRIMARY KEY也就是主键限制!那麽此篇来继续介绍FOREIG...

Day.16 「重复的事情,交给程序去做!」 —— JavaScript 循环回圈

前面学习到了条件判断式,接着我们来学习有点危险的循环回圈,好啦!也没那麽夸张~只是写不好,容易进入...

Day 1 - 环境设置

介绍 先自我介绍一下吧, 笔者来自香港, 很崇拜"开源"这种精神, 慷慨地把自己...