如何在Lua中预定义一个函数?

我如何调用需要在其创建以上调用的函数?我读到了一些关于前向声明的东西,但在这种情况下,Google没有帮助。这是正确的语法是什么?

原文链接 https://stackoverflow.com/questions/6067369

点赞
stackoverflow用户68204
stackoverflow用户68204

Lua 是一种动态语言,函数只是一种可用 () 运算符调用的值类型。因此,你不需要提前声明函数,只需确保在调用时作用域内的变量与你想要的变量相同即可。

对于包含函数的全局变量来说,这并不是问题,因为全局环境是默认查找变量名的地方。然而,对于本地函数,你需要确保在需要调用存储的值的词法点处已经在作用域中定义了本地变量,并且在运行时确保它确实持有一个可调用的值。

例如,下面是一对互相递归的本地函数:

local a,b
a = function() return b() end
b = function() return a() end

当然,这也是使用尾递归允许无限递归但不执行任何操作的示例,但这里的重点是变量声明。通过在任何一个函数存储在其中之前使用 local 声明变量,这些名称将在示例的其余部分的词法作用域中被知晓为本地变量。然后,将两个函数存储起来,每个函数都引用对方的变量。

2011-05-20 05:31:05
stackoverflow用户686008
stackoverflow用户686008

你可以通过在实际声明函数之前声明函数名来预先声明函数:

local func1
local func2 = function()
  func1()
end
func1 = function()
  --做一些事情
end

然而,只有在声明具有本地范围的函数时才需要前向声明。这通常是你想要做的,但 Lua 也支持更像 C 的语法,在这种情况下,前向声明不是必需的:

function func2()
  func1()
end
function func1()
  --做一些事情
end
2011-05-20 11:06:24
stackoverflow用户3166631
stackoverflow用户3166631

在Freeswitch中的嵌入式Lua测试中,前向声明无效:

fmsg("CRIT", "It worked.")
function fmsg(infotype, msg)
   freeswitch.consoleLog(infotype,  msg .. "\n")
end

结果:

[ERR] mod_lua.cpp:203 /usr/local/freeswitch/scripts/foo.lua:1: attempt to call global 'fmsg' (a nil value)

反转顺序(duh)会有效。

2014-07-30 18:09:52
stackoverflow用户3628314
stackoverflow用户3628314

如果在定义之前尝试调用该函数,则此方法对我无效。 我正在nginx conf中使用此Lua脚本。

lua entry thread aborted: runtime error: lua_redirect.lua:109: attempt to call global 'throwErrorIfAny' (a nil value)

代码片段 -

...
throwErrorIfAny()
...

function throwErrorIfAny()
    ngx.say("request not allowed")
    ngx.exit(ngx.HTTP_OK)
end

鉴于其他答案也指出它对他们也不起作用,Lua的前向声明可能与其他工具不兼容。

PS:如果我将函数定义放在之前,然后在之后调用它,则它可以正常工作。

2018-02-23 06:06:58
stackoverflow用户1142045
stackoverflow用户1142045

为了理解 Lua 中的前向引用与 C 的区别,你必须了解 C 编译和 Lua 执行之间的基本区别。

  • 在 C 中,前向引用是 编译时 机制。因此,如果在 C 模块中包含前向声明模板,则任何跟随的代码都将在编译调用时使用该模板。你可以或不可以在同一模块中包含函数实现,在这种情况下,两个声明必须在语义上相同,否则编译器将出错。由于这是一个编译时构造,因此编译后的代码可以以任意顺序执行。

  • 在 Lua 中,前向引用是 运行时 机制,即编译后的函数在代码内部生成一个函数原型,但这只能作为运行时 Lua 变量或值访问,只有执行经过声明并创建 Lua 闭包 后才能访问。在源中声明的顺序无关紧要。重要的是执行的顺序:如果闭包尚未绑定到变量,则执行会抛出“空值”异常。

    如果你使用一个局部变量来保存函数值,则正常的局部变量作用域规则仍然适用:local 声明必须在使用前在源中声明,并且必须在作用域内,否则编译器将编译错误的全局或外部局部引用。因此,使用其他答案中讨论过的局部变量进行前向引用将起作用,_但前提是在第一个调用执行之前将原型绑定到闭包上_。

2018-05-30 12:02:06
stackoverflow用户6438150
stackoverflow用户6438150

如果你使用 OOP(面向对象编程),你可以在其“定义”之前调用任何函数成员。

local myClass = {}
local myClass_mt = { __index = myClass }

local function f1 (self)
    print("f1")
    self:later() --尚未“声明”的局部函数
end

local function f2 (self)
    print("f2")
    self:later() --尚未“声明”的局部函数
end

-- 稍后在你的代码中声明“later”函数:
local function later (self)
    print("later")
end

function myClass.new()    -- 构造函数
    local this = {}

    this = {
        f1 = f1,
        f2 = f2,
        later = later,  -- 你可以通过“self”访问“later”函数
    }

    setmetatable(this, myClass_mt)

    return this
end

local instance = myClass.new()

instance:f1()
instance:f2()

程序输出:

f1
later
f2
later
2018-06-04 05:16:50