Lua局部函数不选择局部变量成员,除非在声明时分配

问题描述 投票:0回答:2

下面的代码有效:

local randomPick = {
    currentPick = 'N/A',
    pickNode = function(self)
        randomPick = node.random(1, table.getn(availableNodes));
        self.currentPick = availableNodes[randomPick];
        return self.currentPick
    end
};

local sentF = function(port, ip, data)
    print('Sent info to ' .. randomPick.currentPick);
end

但是如果我在声明randomPick后分配值,则会出现错误:

local randomPick = {};
randomPick.currentPick = 'N/A';
randomPick.pickNode = function(self)
        randomPick = node.random(1, table.getn(availableNodes));
        self.currentPick = availableNodes[randomPick];
        return self.currentPick
    end

local sentF = function(port, ip, data)
    print('Sent info to ' .. randomPick.currentPick);
end

这不起作用,并抛出此错误。当我为这两个成员分配值时,为什么函数会选择一个空的randomPick

PANIC:调用Lua API时出现不受保护的错误(试图使索引升值'?' (一个数字值))

lua lua-table
2个回答
2
投票

您创建本地表randomPick

一旦调用randomPick.pickNode,就会用随机数值覆盖表randomPick

如果您随后调用setnF,则将索引作为数字的本地上限值randomPick


0
投票
local randomPick = {};
randomPick.currentPick = 'N/A';
randomPick.pickNode = function(self)
   local randomPick = node.random(1, table.getn(availableNodes));
   self.currentPick = availableNodes[randomPick];
   return self.currentPick
end

local function sentF(port, ip, data)
    print('Sent info to ' .. randomPick.currentPick);
end

那应该解决它;问题是您在不声明新本地的情况下使用了两次randomPick,因此您只是覆盖了变量。

当您调用pickNode时,它将randomPick设置为一个新值,当您尝试对其进行索引时,会收到一个错误,因为它现在是一个数字。

您应该问的问题是为什么它甚至在第一个示例中都有效,并且因为在分配之后本地才在作用域内,因此function不会将其视为本地,因此试图全局访问它。

发生的事情是这样的:

local function f(self)
   -- randomPick isn't a local variable yet, so the function is compiled
   -- to use _ENV.randomPick at this point
   randomPick = node.random(1, table.getn(availableNodes));
   self.currentPick = availableNodes[randomPick];
   return self.currentPick
end

local randomPick = {};
-- Local randomPick is introduced here, shadowing the global _ENV.randomPick
randomPick.currentPick = 'N/A'
randomPick.pickNode = f

local function sentF(port, ip, data)
    print('Sent info to ' .. randomPick.currentPick);
end
© www.soinside.com 2019 - 2024. All rights reserved.