在Lua中定义一个函数?

时间:2011-05-20 04:07:58

标签: lua forward-declaration corona

如何调用需要从其创建之上调用的函数?我读了一些关于前向声明的内容,但谷歌在这种情况下并没有帮助。这个的正确语法是什么?

6 个答案:

答案 0 :(得分:32)

Lua是一种动态语言,函数只是一种可以使用()运算符调用的值。所以你真的不需要向前声明函数,以确保调用它时的变量是你认为的变量。

对于包含函数的全局变量,这根本不是问题,因为全局环境是查找解析变量名的默认位置。但是,对于本地函数,您需要确保局部变量已经在您需要调用它存储的值的词汇点的范围内,并且还要确保在运行时它实际上保存了一个可以调用的值

例如,这是一对相互递归的局部函数:

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

当然,这也是使用尾调用来允许无效递归的一个例子,但这里的重点是声明。通过在存储函数之前使用local声明变量,已知这些名称是本示例其余部分的词法范围内的局部变量。然后存储两个函数,每个函数引用另一个变量。

答案 1 :(得分:10)

您可以在声明实际函数体之前通过声明其名称来转发声明函数:

local func1
local func2 = function()
  func1()
end
func1 = function()
  --do something
end

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

function func2()
  func1()
end
function func1()
  --do something
end

答案 2 :(得分:1)

在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:尝试呼叫全球' fmsg' (零值)

撤销订单(duh)工作。

答案 3 :(得分:1)

要理解Lua中的前向引用与C相比如何工作,您必须理解C编译和Lua执行之间的根本区别。

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

  • 在Lua中,正向引用是运行时机制,因为已编译的函数在代码内部生成函数原型,但这只能作为运行时Lua变量或值之后访问。执行有 传递了创建Lua 闭包的声明。这里源中的声明顺序并不重要。执行顺序很重要:如果闭包尚未绑定到变量,则执行抛出“零值”异常。
    如果您使用的是用于保存函数值的局部变量,然后正常的本地作用域规则仍然适用:local声明必须在源中使用之前必须在范围内,否则编译器将在错误的全局或外部本地引用中编译。因此,正如其他答案中所讨论的那样,使用locals进行前向引用将起作用,但只有在第一次调用执行之前Protos被绑定到闭包。

答案 4 :(得分:0)

如果我尝试在定义之前调用该函数,则对我不起作用。我在nginx conf中使用这个Lua脚本。

  

lua条目线程已中止:运行时错误:lua_redirect.lua:109:尝试调用全局'throwErrorIfAny'(零值)

代码段 -

...
throwErrorIfAny()
...

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

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

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

答案 5 :(得分:0)

如果您使用OOP,您可以在其“定义”之前调用任何函数成员。

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

local function f1 (self)

    print("f1")
    self:later() --not yet "delared" local function
end

local function f2 (self)

    print("f2")
    self:later() --not yet "declared" local function   
end
--...
--later in your source declare the "later" function:
local function later (self)

    print("later")   
end

function myClass.new()    -- constructor
    local this = {}

    this = {
        f1 = f1,
        f2 = f2,
        later = later,  --you can access the "later" function through "self"
    }

    setmetatable(this, myClass_mt)

    return this
end

local instance = myClass.new()

instance:f1()
instance:f2()

节目输出:

f1
later
f2
later