【发布时间】:2011-08-29 08:53:10
【问题描述】:
如何调用需要从其创建之上调用的函数?我读了一些关于前向声明的东西,但谷歌在这种情况下没有帮助。正确的语法是什么?
【问题讨论】:
标签: lua forward-declaration coronasdk
如何调用需要从其创建之上调用的函数?我读了一些关于前向声明的东西,但谷歌在这种情况下没有帮助。正确的语法是什么?
【问题讨论】:
标签: lua forward-declaration coronasdk
Lua 是一种动态语言,函数只是一种可以用() 运算符调用的值。所以你真的不需要转发声明函数,只要确保你调用它时范围内的变量就是你认为的变量。
对于包含函数的全局变量,这根本不是问题,因为全局环境是解析变量名的默认位置。然而,对于局部函数,你需要确保局部变量已经在你需要调用它存储的值的词法点的范围内,并且还要确保在运行时它确实持有一个可以调用的值.
例如,这里有一对相互递归的局部函数:
local a,b
a = function() return b() end
b = function() return a() end
当然,这也是一个使用尾调用来允许不执行任何操作的无限递归的示例,但这里的重点是声明。通过在其中存储函数之前使用local 声明变量,这些名称在示例的其余部分的词法范围内被称为局部变量。然后存储两个函数,每个函数都引用另一个变量。
【讨论】:
您可以通过在声明实际函数体之前声明其名称来转发声明函数:
local func1
local func2 = function()
func1()
end
func1 = function()
--do something
end
但是,只有在声明具有本地范围的函数时才需要前向声明。这通常是你想要做的,但 Lua 也支持更像 C 的语法,在这种情况下不需要前向声明:
function func2()
func1()
end
function func1()
--do something
end
【讨论】:
local func1 声明了一个具有该名称的 new 变量并留下了第一个 func1孤立并仍设置为nil。
在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)有效。
【讨论】:
要了解 Lua 中的前向引用与 C 相比如何工作,您必须了解 C 编译和 Lua 执行之间的根本区别。
在 C 中,前向引用是一种编译时 机制。因此,如果您在 C 模块中包含前向声明模板,那么您后面的任何代码都将在编译调用时使用此模板。您可能会或可能不会在同一个模块中包含函数实现,在这种情况下,两个声明必须在语义上相同,否则编译器会出错。由于这是一个编译时构造,因此编译后的代码可以按任意顺序执行。
在 Lua 中,前向引用是 runtime 机制,因为编译后的函数会在代码内部生成函数原型,但这只能作为运行时 Lua 变量或值在执行有
传递了创建 Lua closure 的声明。这里源中的声明顺序无关紧要。重要的是执行顺序:如果闭包尚未绑定到变量,则执行将抛出“nil value”异常。
如果您使用的是本地变量来保存函数值,那么正常的局部作用域规则仍然适用:local 声明必须先于它在源中的使用并且必须在作用域内,否则编译器将编译错误的全局或外部局部引用。因此,在其他答案中讨论的使用本地变量的前向引用将起作用,但前提是 Protos 在执行第一次调用之前绑定到闭包。
【讨论】:
如果我尝试在定义之前调用该函数,则对我不起作用。我在 nginx conf 中使用这个 Lua 脚本。
lua 入口线程中止:运行时错误:lua_redirect.lua:109:尝试调用全局 'throwErrorIfAny'(一个 nil 值)
代码sn-p -
...
throwErrorIfAny()
...
function throwErrorIfAny()
ngx.say("request not allowed")
ngx.exit(ngx.HTTP_OK)
end
鉴于其他一些答案也指出它也不适用于他们,Lua 的前向声明可能不适用于其他工具。
PS:如果我把函数定义放在之前,然后在病房之后调用它就可以了。
【讨论】:
如果您使用 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
【讨论】: