There are some basic misunderstandings here, so I'll try to break it down step by step. Consider the first part of the initial given code.
function gen (name) -- define a function named "gen"
return -- return
{ -- a table
function name () -- containing a function...
-- et cetra ...
When you write a pair of matched curly braces {...} in Lua you are defining a table. Things you write inside the braces become the contents of the table. This is called a table constructor.
The error you are getting in this code is because you have tried to write a statement where Lua expects an expression. The difference between these things is somewhat technical, but basically, expressions represent a value and may contain things like numbers, strings, operators, table constructors and function calls. A statement is a piece of code that represents an action like assigning an expression to a variable, a function call (which can be an expression or a statement), or a complex structure like an if or while block (which probably has other statements inside).
function name() ... end is a statement in Lua because it assigns the function to the global variable name. It is also possible to have an function as an expression, but then you can't give it a name (in the same way). This looks like function() ... end. That's why Lua said it was expecting ( after function. Giving an expression a name in Lua in the same thing as an assignment, so it is a statement.
This may be a little bit confusing in the case of a table constructor, as you can put something that looks a lot like an assignment statement inside of a table constructor. For example {x = 3} or {name = function() ... end} are perfectly fine expressions, but here the x = or name = means something different than it does as a statement outside of a table constructor. It doesn't mean to assign to a variable called x or name, but instead to add a field to the table with that name.
For example:
table1 = {x = 3}
print(x) -- nil
print(table1.x) -- 3
table2 = {name = function() print("hello!") end}
name() -- error!
table2.name() -- hello!
Now, consider
function gen(name)
function name()
print("hello!")
end
end
When you put an identifier between function and (), Lua uses literally what you wrote as the name of the function. So:
gen("f")
f() -- error
name() -- hello!
You need to do something special to assign a value to a variable that is determined at run-time. For local variables, this is possible only with the debug API (and only then for variable names that already exist otherwise). For global variables, you can use the global table.
When you assign a value to a global variable, Lua internally has to keep track of it somehow. It does this using a table, just the same as any other table. By default, the variable _G contains a reference to that table.
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
If used as I did above, this isn't very useful. However, remember that in Lua, table.x is actually shorthand for table["x"]. By using the [] syntax instead of the . syntax, we gain the flexibility to do define a global variable dynamically.
_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
This is essentially what lhf's answer does. It defines assigns a function to a global variable with a name determined by the argument of the surrounding function. It should work perfectly if you want to define a global function.
Now consider your second answer block of code:
function gen (self, name, arg2)
return
{
[name] = function (arg3)
-- et cetra ...
Here again, we are in a table constructor, so we are not defining a global variable, we are creating a table field whose value is a function. As before, using the [] syntax allows the field's name to be determined by the name variable. Consider:
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
This also works fine if your intent is to for the function to be stored in the table.
You have to decide where you want your function to be stored, and put it there. In either the global environment or as a field in a table, you can choose the name based on the argument of a function.
Note that the function itself doesn't have a name. Lua functions don't inherently have names. They are just (usually) stored in variables or fields, and the name of the variable or field is thought of as the name of the function.
Another possibility, then, is to not give a name inside the generator at all. For example:
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
[name] = function()