我正在尝试整理一些代码并创建函数生成器。所以我将一堆参数传递给一个创建嵌套函数的函数;第一个是嵌套函数的所需名称。
function gen (name)
return
{
function name ()
return
{
...
}
end
}
end
然后我用不同的名称调用gen
函数几次,以获得内部具有不同值的多个name
函数。
显然它不能像我想要的那样工作。我得到的确切错误是
'('预计在'name'附近
令人惊讶的是,当我使用name = function ()
表示法时,我得到了一些远在下游的其他错误。
我已经使用了一些代码,但我的知识不足以使用任何构造,但最初非常庞大的版本。
更新#1 此
function gen (self, name, arg2)
return
{
[name] = function (arg3)
return
{
data = arg3
}
end
}
end
for k,v in pairs (gen (name, "xarg")) do print(k,v) end
print (xarg)
返回
xarg function: 0x1365390
nil
使用_G[name]
我根本没有运气。
更新#2
所以我没有找到解决方案并转而使用t[name]
,代价是丢弃(arg3)
。
答案 0 :(得分:1)
如果要创建名为name
的全局函数,请使用
function gen (name)
_G[name] = function ()
-- body here
end
end
答案 1 :(得分:1)
这里有一些基本的误解,所以我会尝试逐步分解。考虑初始给定代码的第一部分。
function gen (name) -- define a function named "gen"
return -- return
{ -- a table
function name () -- containing a function...
-- et cetra ...
当您在Lua中编写一对匹配的大括号{...}
时,您正在定义一个表。你在大括号内写的东西成了桌子的内容。这称为表构造函数。
您在此代码中遇到的错误是因为您尝试编写语句,其中Lua期望表达式。这些东西之间的区别在某种程度上是技术性的,但基本上,表达式表示一个值,可能包含数字,字符串,运算符,表构造函数和函数调用等内容。语句是一段代码,表示将表达式赋值给变量,函数调用(可以是表达式或语句),或复杂结构,如if
或while
block(里面可能还有其他语句)。
function name() ... end
是Lua中的一个语句,因为它将函数分配给全局变量name
。也可以将函数作为表达式,但是你不能给它一个名字(以同样的方式)。这看起来像function() ... end
。这就是为什么Lua说在(
之后期待function
的原因。在Lua中为表达式赋予与赋值相同的名称,因此它是一个声明。
在表构造函数的情况下,这可能有点令人困惑,因为你可以在表构造函数中放置一些看起来很像赋值语句的东西。例如,{x = 3}
或{name = function() ... end}
是非常精细的表达式,但x =
或name =
表示与表构造函数之外的语句不同。它并不意味着分配给名为x
或name
的变量,而是将字段添加到具有该名称的表中。
例如:
table1 = {x = 3}
print(x) -- nil
print(table1.x) -- 3
table2 = {name = function() print("hello!") end}
name() -- error!
table2.name() -- hello!
现在,考虑一下
function gen(name)
function name()
print("hello!")
end
end
当您在function
和()
之间放置一个标识符时,Lua会根据您所写的内容使用该函数的名称。所以:
gen("f")
f() -- error
name() -- hello!
您需要执行一些特殊操作,以便为在运行时确定的变量赋值。对于局部变量,这仅适用于调试API(并且仅适用于已存在的变量名称)。对于全局变量,您可以使用全局表。
当你为全局变量赋值时,Lua内部必须以某种方式跟踪它。它使用表格执行此操作,与任何其他表格相同。默认情况下,变量_G
包含对该表的引用。
print(x) -- nil
print(_G.x) -- nil
x = 3
print(x) -- 3
print(_G.x) -- 3
_G.x = 4
print(x) -- 4
print(_G.x) -- 4
print(_G == _G._G) -- true
如果像我上面那样使用,这不是非常有用。但请记住,在Lua中,table.x
实际上是table["x"]
的简写。通过使用[]
语法而不是.
语法,我们可以灵活地动态定义全局变量。
_G["y"] = 5
print(y) -- 5
print(_G.y) -- 5
print(_G["y"]) -- 5
print(z) -- nil
name = "z"
_G[name] = 6
print(z) -- 6
这实际上是lhf的回答。它定义了一个函数给一个全局变量,其名称由周围函数的参数决定。如果你想定义一个全局函数,它应该可以正常工作。
现在考虑你的第二个代码块:
function gen (self, name, arg2)
return
{
[name] = function (arg3)
-- et cetra ...
同样,我们在一个表构造函数中,所以我们没有定义一个全局变量,我们正在创建一个表字段,其值是一个函数。与以前一样,使用[]
语法允许字段的名称由name
变量确定。考虑:
table = gen(nil, "xarg")
-- table = {xarg = function(arg3) return {data = arg3} end}
print(table.xarg) -- function ...
table2 = table.xarg("mydata")
print(table2.data) -- mydata
table3 = table.xarg("myotherdata")
print(table3.data) -- myotherdata
print(table2 == table3) -- false
-- you can assign this to a global variable if you want later
-- (but then why put it in a table to begin with?)
xarg = table.xarg
print(xarg("mythirddata").data) -- mythirddata
name2 = "xarg2"
table_xarg2 = gen(nil, name2)
_G[name2] = table_xarg2[name2]
print(xarg2("mylastdata").data) -- mylastdata
如果您的意图是将函数存储在表中,这也可以正常工作。
您必须决定将功能存储在何处,并将其放在那里。在全局环境中或作为表中的字段,您可以根据函数的参数选择名称。
请注意,该功能本身没有名称。 Lua函数本身没有名字。它们(通常)存储在变量或字段中,变量或字段的名称被认为是函数的名称。
另一种可能性是,根本不在发电机内部给出一个名称。例如:
function gen(arg1)
return function(arg2)
return {data1 = arg1, data2 = arg2}
end
end
xarg1 = gen("a1")
xarg2 = gen("a2")
record1 = xarg1("b1")
record2 = xarg2("b2")
print(record1.data1) -- a1
print(record1.data2) -- b1
print(record2.data1) -- a2
print(record2.data2) -- b2