函数参数作为另一个函数的名称?

时间:2018-02-19 21:59:33

标签: function lua

我正在尝试整理一些代码并创建函数生成器。所以我将一堆参数传递给一个创建嵌套函数的函数;第一个是嵌套函数的所需名称。

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)

2 个答案:

答案 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期望表达式。这些东西之间的区别在某种程度上是技术性的,但基本上,表达式表示一个值,可能包含数字,字符串,运算符,表构造函数和函数调用等内容。语句是一段代码,表示将表达式赋值给变量,函数调用(可以是表达式或语句),或复杂结构,如ifwhile block(里面可能还有其他语句)。

function name() ... end是Lua中的一个语句,因为它将函数分配给全局变量name。也可以将函数作为表达式,但是你不能给它一个名字(以同样的方式)。这看起来像function() ... end。这就是为什么Lua说在(之后期待function的原因。在Lua中为表达式赋予与赋值相同的名称,因此它是一个声明。

在表构造函数的情况下,这可能有点令人困惑,因为你可以在表构造函数中放置一些看起来很像赋值语句的东西。例如,{x = 3}{name = function() ... end}是非常精细的表达式,但x =name =表示与表构造函数之外的语句不同。它并不意味着分配给名为xname的变量,而是将字段添加到具有该名称的表中。

例如:

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