1

我有一个场景,我想将输入输入 printf 实现并预处理参数。...我的目标是获取输入,必要时处理变量参数 ( ),并将其输入到 string.format。我遇到的问题是数据在传递时会“丢失”。我发现...没有传入 nil 值。例如,如果正常运行通过nil, false, false,则调用路径中的后续下线函数只能看到false, false. 当转换为内部表()进行处理时,我在这里缺少什么来保留数据{...}

编辑:我最初的评估是不正确的。nil 永远不会被保留(即使在 printf 中)。如果...打印,表格可以是空的(对于所有 nil)或者只有在包含“真实”数据的地方有索引值(例如 TablePrint 给出 { [2] = false, [3] = false })

在游戏中运行的,但我可以在不使用任何游戏数据的情况下复制该行为。

local function TablePrint (data, indent)
    if not indent then indent = 0 end

    local output = string.rep(" ", indent) .. "{\r\n"
    indent = indent + 2
    
    for k, v in pairs(data) do
        output = output .. string.rep(" ", indent)
        
        if (type(k) == "number") then
            output = output .. "[" .. k .. "] = "
        elseif (type(k) == "string") then
            output = output  .. k ..  "= "   
        end
        
        if (v == nil) then
            output = output .. 'nil' .. ",\r\n"
        elseif (v == NULL) then
            output = output .. 'NULL' .. ",\r\n"
        elseif (type(v) == "number") then
            output = output .. v .. ",\r\n"
        elseif (type(v) == "string") then
            output = output .. "\"" .. v .. "\",\r\n"
        elseif (type(v) == "table") then
            output = output .. TablePrint(v, indent + 2) .. ",\r\n"
        else
            output = output .. "\"" .. tostring(v) .. "\",\r\n"
        end
    end
    
    output = output .. string.rep(" ", indent-2) .. "}"
    
    return output
end

local function NormalizeValue(v)
    local output

    if (v == nil) then
        output = 'nil'
    elseif (v == NULL) then
        output = 'NULL'
    elseif (type(v) == "number" or type(v) == "string") then
        output = v
    elseif (type(v) == "table") then
        output = TablePrint(v)
    else
        output = tostring(v)
    end

    return output
end

local function NormalizeArgs(...)
    local args = {...}
    --print(TablePrint(args))
    local normalizedArgs = {}

    for _,v in ipairs(args) do
        table.insert(normalizedArgs, NormalizeValue(v))
    end

    return unpack(normalizedArgs)
end

local function printf(message, ...)
    --print(TablePrint({...}))
    local output

    if (type(message) == "number") then
        output = message
    elseif (type(message) == "string") then
        output = string.format(message, NormalizeArgs(...))
        --this call to string.format succeeds if used
        --output = string.format(message, ...)
    elseif (type(message) == "table") then
        output = TablePrint(message)
    else
        output = tostring(message)
    end

    print(output)
end

--this line fails since nil isn't preserved across call boundaries
--printf('initial conditions, cursor: %s, confirm window: %s, isfinished: %s', nil, nil, nil)
--this line fails since nil isn't preserved across call boundaries
printf('initial conditions, cursor: %s, confirm window: %s, isfinished: %s', nil, false, false)
--this will succeed
printf('initial conditions, cursor: %s, confirm window: %s, isfinished: %s', false, false, false)
--in the normal impl the final parameter is supplied by a call to a local function
printf('initial conditions, cursor: %s, confirm window: %s, isfinished: %s', gamelib.Cursor.ID(), gamelib.Window('Confirm').Open(), nil)
4

1 回答 1

1

您可以使用select来全面检查.... 递归地返回多个值可能比创建一个表来解压它更容易:

local function NormalizeArgs(...)
    if select('#', ...) > 0 then
        return NormalizeValue(select(1, ...)), NormalizeArgs(select(2, ...))
    end
end
于 2022-01-18T21:30:44.463 回答