Lua関数のシグネチャを決定する方法はありますか?
-
02-07-2019 - |
質問
最近、 Lee Baldwin は、汎用の可変引数メモ関数。必要なパラメーターが1つだけの単純な関数を返すことをお勧めします。これが私の総偽の試みです:
local function memoize(f)
local cache = {}
if select('#', ...) == 1 then
return function (x)
if cache[x] then
return cache[x]
else
local y = f(x)
cache[x] = y
return y
end
end
else
return function (...)
local al = varg_tostring(...)
if cache[al] then
return cache[al]
else
local y = f(...)
cache[al] = y
return y
end
end
end
end
明らかに、このコンテキストでは select( '#'、...)
が失敗し、とにかく私が望んでいることを本当に実行しません。 f が期待する引数の数を memoize 内で伝える方法はありますか?
"いいえ"あなたが確かに知っているなら、良い答えです。 2つの別個の memoize 機能を使用することは大したことではありません。
解決
デバッグ情報にアクセスし、ソースコードからこれを判断できると思いますが、基本的には「いいえ」です、申し訳ありません。
他のヒント
はい、Lua関数ではなくC関数です。それは少し拷問的で少し大ざっぱです。
debug.getlocal
は呼び出された関数で機能するため、問題の関数を呼び出す必要があります。呼び出しが十分なパラメーターを渡さない限り、 ...
のヒントは表示されません。以下のコードは20個のパラメーターを試します。
debug.sethook
に" call"イベントは、コードを実行する前に関数をインターセプトする機会を与えます。
このアルゴリズムはLua 5.2で動作します。古いバージョンは似ていますが、同じではありません:
assert(_VERSION=="Lua 5.2", "Must be compatible with Lua 5.2")
小さなヘルパーイテレータ(効率のためにインライン化できます):
local function getlocals(l)
local i = 0
local direction = 1
return function ()
i = i + direction
local k,v = debug.getlocal(l,i)
if (direction == 1 and (k == nil or k.sub(k,1,1) == '(')) then
i = -1
direction = -1
k,v = debug.getlocal(l,i)
end
return k,v
end
end
署名を返します(ただし、パラメーターカウントを返し、代わりにVarargsを使用できます):
local function dumpsig(f)
assert(type(f) == 'function',
"bad argument #1 to 'dumpsig' (function expected)")
local p = {}
pcall (function()
local oldhook
local hook = function(event, line)
for k,v in getlocals(3) do
if k == "(*vararg)" then
table.insert(p,"...")
break
end
table.insert(p,k) end
debug.sethook(oldhook)
error('aborting the call')
end
oldhook = debug.sethook(hook, "c")
-- To test for vararg must pass a least one vararg parameter
f(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20)
end)
return "function("..table.concat(p,",")..")"
end
Luaではそれができないと確信しています。
所属していません StackOverflow