28

Is it possible in lua to execute a function from a string representing its name?
i.e: I have the string x = "foo", is it possible to do x() ?

If yes what is the syntax ?

Gregoire
  • 24,219
  • 6
  • 46
  • 73

5 Answers5

43

To call a function in the global namespace (as mentioned by @THC4k) is easily done, and does not require loadstring().

x='foo'
_G[x]() -- calls foo from the global namespace

You would need to use loadstring() (or walk each table) if the function in another table, such as if x='math.sqrt'.

If loadstring() is used you would want to not only append parenthesis with ellipse (...) to allow for parameters, but also add return to the front.

x='math.sqrt'
print(assert(loadstring('return '..x..'(...)'))(25)) --> 5

or walk the tables:

function findfunction(x)
  assert(type(x) == "string")
  local f=_G
  for v in x:gmatch("[^%.]+") do
    if type(f) ~= "table" then
       return nil, "looking for '"..v.."' expected table, not "..type(f)
    end
    f=f[v]
  end
  if type(f) == "function" then
    return f
  else
    return nil, "expected function, not "..type(f)
  end
end

x='math.sqrt'
print(assert(findfunction(x))(121)) -->11
gwell
  • 2,695
  • 20
  • 20
  • What if you want to call a non global function. For example, I need to call a function in another module, which has its own variables. If I make a copy of this function in the current namespace then I'll be making local copies of their variables too... – Luke Allison Aug 21 '19 at 05:36
18

I frequently put a bunch of functions in a table:

functions = {
       f1 = function(arg) print("function one: "..arg) end,
       f2 = function(arg) print("function two: "..arg..arg) end,
       ...,
       fn = function(arg) print("function N: argh") end,
}

Then you can use a string as an table index and run your function like this

print(functions["f1"]("blabla"))
print(functions["f2"]("blabla"))

This is the result:

function one: blabla
function two: blablablabla

I find this to be cleaner than using loadstring(). If you don't want to create a special function table you can use _G['foo'].

koniu
  • 578
  • 5
  • 15
  • Doesn't answer the question as stated but does offer a simple workaround that I'll end up using. – Sled Jun 25 '18 at 14:49
12

loadstring is not the answer here. For starters you would need a return in the string, and other details I won't go into.

THC4k has the right idea; if you have the function name in the variable x, then the call you want is

_G[x](arg1, arg2, ...)
Norman Ramsey
  • 198,648
  • 61
  • 360
  • 533
6

Names are not unique, there can be many functions names foo in different namespaces. But _G['foo'] is foo in the global namespace.

Jochen Ritzel
  • 104,512
  • 31
  • 200
  • 194
3

It sounds like you want to do an 'eval', which is supported in Lua like so:

assert(loadstring(x))()

You'll probably want to concatenate the "()" onto x first, though.

perimosocordiae
  • 17,287
  • 14
  • 60
  • 76
  • What if you want to call a non global function. For example, I need to call a function in another module, which has its own variables. If I make a copy of this function in the current namespace then I'll be making local copies of their variables too... – Luke Allison Aug 21 '19 at 05:43