【问题标题】:Local functions calling each other本地函数相互调用
【发布时间】:2016-11-24 22:43:28
【问题描述】:

我有两个偶尔会互相调用的函数,它们是使用它们构建另一个函数的模块的本地函数。该模块有点类似于这段代码:

local function iseven(n)
    if n == 1 then
        return false
    else
        return isodd(n - 1)
    end
end

local function isodd(n)
    if n == 1 then
        return true
    else
        return iseven(n - 1)
    end
end

local evenOrOdd = function(n)
    return iseven(n) and "Even" or "Odd"
end

return evenOrOdd

问题是,当从另一个文件调用evenOrOdd 时,我收到错误attempt to call global 'isodd' (a nil value)

我注意到,如果我将 iseven 设置为全局,则不会发生这种情况,但我想将它们保留在我的模块中。

我什至尝试在声明 iseven 的行之前放置一个虚拟函数声明 (local function isodd() end)。我还尝试只插入 local isodd 来代替虚拟函数声明,但在这两种方式中它都不起作用,并且我得到了不同类型的错误。

我知道这是因为 Lua 有闭包,当声明 iseven 时,它会捕获 isodd 的实际值,即 nil 或虚拟函数,之后对其进行修改不算数,而是有没有办法绕过这个?

【问题讨论】:

  • Lua 中的前向声明示例:local f; local function g() return f() end; function f() return g() end
  • @Egor Skriptunoff 哦,对了。正如我在问题中所说,我尝试过。但似乎我忘了在function isodd(n) 之前删除local,我得到了attempt to call upvalue 'isodd' (a nil value) 错误。谢谢。
  • 您提供的代码的错误消息应该是attempt to call global 'isodd' (a nil value),这应该可以解释发生了什么。
  • 小心从其他语言中继承“前向声明”的概念。没有要求以后有“实际声明”。在 Lua 中,只声明局部变量(包括参数)。函数是在执行包含它的表达式时从函数定义在运行时创建的值。这样的值通常分配给变量。 (function () 语法是简写。)同样,没有声明函数。

标签: function recursion lua local


【解决方案1】:

问题是在iseven 中对isodd 的调用使用了一个全局 变量,而不是稍后定义的本地变量。

按照@Egor 的建议使用前向声明:

local iseven, isodd

function iseven(n)
...
end

function isodd(n)
...
end

...

【讨论】:

  • 我不明白。在执行 iseven 的时候,isodd 不存在的问题,因此编译器默认为一个不存在的全局 isodd 吗?所以全局函数可以在代码后面,但全局函数不能?
【解决方案2】:

解决这个问题的另一种方法是使用表格。普通的局部变量可能更有效,但对于表,您不需要管理声明。

local T = {}

local function evenOrOdd(n)
    return T.iseven(n) and "Even" or "Odd"
end

function T.iseven(n)
    -- code
end

这样做的要点是,因为表格是在顶部定义的,所以它下面的所有内容都可以访问它,并且您可以动态更改它的内容。 当evenOrOdd 被调用时,T.iseven 应该已经被定义了,即使它在evenOrOdd 被定义时没有被定义。

【讨论】:

    【解决方案3】:

    更好地检查num%2 - 除法的其余部分

    【讨论】:

    • 这只是一个展示我的函数如何工作的例子。它们真的太长了,无法在此处复制它们,无论如何都可以回答问题(参见 cmets)。
    猜你喜欢
    • 1970-01-01
    • 2015-01-19
    • 2017-02-15
    • 2013-01-25
    • 1970-01-01
    • 2016-10-18
    • 2015-03-08
    • 1970-01-01
    • 2021-10-04
    相关资源
    最近更新 更多