命名函数和匿名函数的区别(Lua)

4
这些myFunc有何区别?
代码 1
function wrapper()
    local someVariable = 0;
    function myFunc(n)
        if n > 0 then return myFunc(n-1) end
    end
    return myFunc;
end

代码 2

function wrapper()
    local someVariable = 0;
    local myFunc = function(n)
        if n > 0 then return myFunc(n-1) end
    end
    return myFunc;
end

代码 3

function wrapper()
    local someVariable = 0;
    local myFunc;
    myFunc = function(n)
        if n > 0 then return myFunc(n-1) end
    end;
    return myFunc;
end

当我在 myFunc 函数内部引用函数名 myFunc 时,它们的行为是不一样的(例如,upvalue someVariable 会有问题)。

2个回答

5

[编辑:我错误地阅读了您的代码#2。]

代码#1将myFunc的全局值设置为该函数。因此,每次调用wrapper时,都会将此全局值设置为新值。此外,对于任何对myFunc的引用调用,都将是对此全局变量(可修改)而不是对闭包的上值的引用。

代码#2设置一个局部变量myFunc。然而,由于Lua的规则,只有在定义它的语句完成后,该局部变量才会进入作用域。这使您可以执行以下操作:

local x = x or 5

表达式中的x是先前声明的本地或全局变量。新的xx或5表达式被评估之后才会进入范围。

函数定义也是如此。因此,对myFunc的任何引用都将是对全局变量而不是局部变量的引用。

代码#3创建了一个局部变量myFunc。然后将一个函数设置到该变量中。因为函数是在局部变量进入范围之后创建的,所以函数中对myFunc的引用将引用局部变量而不是全局变量。

请注意,local function X等同于local X; X = function...,而不是local X = function...


谢谢!所以当我在代码1中使用local function myFunc()时,它们都变得相同了吗? - HKTonyLee
@HKTonyLee:实际上,不是这样的。我完全误读了你的第二点。请看我的新版本。 - Nicol Bolas

2
尼科尔的回答大部分正确,但有一件事值得指出:
在代码2中,MyFunc不需要成为全局变量,它可以是某个外部范围的局部变量,这将成为您创建的此函数的上值(对代码1也适用)。例如,这将打印100:
local function myFunc(n) return 100 end
function wrapper()
    local someVariable = 0;
    local myFunc = function(n)
        if n > 0 then return myFunc(n-1) end
    end
    return myFunc;
end
print(wrapper()(1))

因此,总结一下,您可以使用四种方法来定义myFunc:
  1. local myFunc; myFunc = function(n) ... return myFunc(n-1) end
  2. local function myFunc(n) ... return myFunc(n-1) end
  3. local myFunc = function(n) ... return myFunc(n-1) end
  4. myFunc = function(n) ... return myFunc(n-1) end
1和2是完全等效的。3不会按您所期望的工作,因为它将在执行“local myFunc”时使用可用的任何myFunc定义(可能指向MyFunc的upvalue或全局变量)。 4将起作用,但仅因为它将新创建的函数分配给(再次)upvalue或全局变量(并在函数体中引用相同的值)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接