web-dev-qa-db-ja.com

関数名の文字列から関数を呼び出す

その名前を表す文字列から関数を実行することは可能ですか?
i.e:私は_string x = "foo"_を持っていますが、x()を実行できますか?

はいの場合、構文は何ですか?

23
Gregoire

@ THC4kで言及されているように、グローバル名前空間の関数を呼び出すのは簡単で、loadstring()は必要ありません。

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

関数が別のテーブルにある場合、_x='math.sqrt'_などの場合は、loadstring()(または各テーブルをウォークする)を使用する必要があります。

loadstring()を使用する場合は、括弧を楕円_(...)_で追加してパラメーターを許可するだけでなく、returnを前に追加することもできます。

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

またはテーブルを歩く:

_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
_
39
gwell

私は頻繁に関数の束をテーブルに入れました:

_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,
}
_

次に、文字列をテーブルインデックスとして使用して、次のように関数を実行できます。

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

これが結果です:

_function one: blabla
function two: blablablabla
_

これはloadstring()を使用するよりもクリーンであることがわかりました。特別な関数テーブルを作成したくない場合は、__G['foo']_を使用できます。

13
koniu

loadstringはここでは答えではありません。まず、文字列にreturnが必要ですが、その他の詳細については説明しません。

THC4kは正しい考えを持っています。変数xに関数名がある場合、必要な呼び出しは

_G[x](arg1, arg2, ...)
11
Norman Ramsey

名前は一意ではなく、さまざまな名前空間に多くの関数名fooが存在する可能性があります。だが _G['foo']は、グローバル名前空間のfooです。

5
Jochen Ritzel

Luaでサポートされている「評価」を実行したいようです:

assert(loadstring(x))()

ただし、おそらく最初に "()"をxに連結する必要があります。

2
perimosocordiae