LUA

2012-05-05 9 views
2

に関数の引数の名前を取得します。私は実際にそれがデモの値(まあ、だ「MyVariableName」を印刷しないでできるようにしたいと思います目的)。LUA

明らかに私は文字列を渡すことができますが、それは余分な引用符を必要とし、私はその値を印刷したいと思います。

例えば、

MyVariable = 4 
PrintVariable(MyVariable) 

は "MYVARIABLEが4である" か、私はこれが不要であるとして

PrintVariable(MyVariable, "MyVariable") 

のように名前と変数を複製する必要はしたくないものは何でも

印刷し複製。

ルアはそれを処理できますか?

変数名を引用符で渡し、値を取得するためにloadstringを使用していますが、余分な不要な引用符を使わずに変数を直接渡すだけです(これはdebug.getlocalとは思ったが終了する名前の代わりに値を返す)。ここで


すべて3は同じことを印刷する必要があります。この場合

function printme1(var, val) 
    print(var.." = "..val) 
end 

function printme2(v) 
    local r 
    loadstring("r = "..v)() -- equivalent to r = a but must be used since v is a string representing a and not the object a 
    print(v.." = "..tostring(r)) 
end 

function printme3(v) 
    -- unknown 
end 

a = 3 

printme1("a", a) 
printme2("a") 
printme3(a) 

モック例です。明らかにprintme3が最も便利です。

+0

loadstring(私の例を参照してください)を呼び出さなくても実行できますが、引用符なしでは実行できません。強くない。 APIには、必要なものを教えてくれるものは何もありません。呼び出し元のスコープ内で渡された値を持つローカルを探すことはできますが、それは信頼できません。とにかくそれを書く方法を教えてくれるでしょう(私の答えを見てください)。 – Mud

答えて

0

私には悪い知らせがあります。関数のパラメータ名は、関数の先頭に表示されているとおりにアクセスできますが、呼び出し関数内の名前に正確にアクセスするためのデータは存在しません。以下を参照してください。

function PrintVariable(VariableToPrint) 
    --we can use debug.getinfo() to determine the name 'VariableToPrint' 
    --we cannot determine the name 'MyVariable' without some really convoluted stuff (see comment by VBRonPaulFan on his own answer) 
    print(VariableToPrint); 
end 

MyVariable = 4 
PrintVariable(MyVariable) 

これを説明するために、我々は行っていた場合を想像:あなたはLuaのであれば

x = 4 
MyVariable = x 
MyOtherVariable = x 
x = nil 

PrintVariable(MyVariable) 

は今、どのような名前を渡されてしまう変数にメタデータに添付します関数に?はい、あなたは渡された変数を探してdebug.getint()でスタックを歩くことができますが、いくつかの参照を見つけることができます。 また、次の点を考慮してください:

PrintVariable("StringLiteral") 

あなたはその変数を何と呼びますか?値はありますが、名前はありません。

+0

OPは彼が望む変数名を回復することはできませんが、 "ローカル変数名が存在しなくなりました"ということは真実ではありません。あなたは 'debug.getlocal'を使ってそれらをすべて回復できます。ただし、スタックレベルと作成された順序に従って回復されます。値を関数に渡すために使用されたものを回復する方法はありません。 – Mud

+0

私はネイサンが欲しいものを理解していません(または私はあなたを理解しません)...私は使用するコードを含むように私のポストを更新しましたが、代わりに文字列を渡す必要があります。 – Uiy

+0

申し訳ありませんが、書式設定されたコード例を使って自分自身を少しはっきりと説明しようと私の投稿を編集しました。 –

0

デバッグライブラリで、このようなものを行うことができます...このようなものは、あなたが探しているように見えるものを行います。

function a_func(arg1, asdf) 
    -- if this function doesn't use an argument... it shows up as (*temporary) in 
    -- calls to debug.getlocal() because they aren't used... 
    if arg1 == "10" then end 
    if asdf == 99 then end 
    -- does stuff with arg1 and asdf? 
end 

-- just a function to dump variables in a user-readable format 
function myUnpack(tbl) 
    if type(tbl) ~= "table" then 
     return "" 
    end 

    local ret = "" 
    for k,v in pairs(tbl) do 
     if tostring(v) ~= "" then 
      ret = ret.. tostring(k).. "=".. tostring(v).. ", " 
     end 
    end 
    return string.gsub(ret, ", $", "") 
end 

function hook() 
    -- passing 2 to to debug.getinfo means 'give me info on the function that spawned 
    -- this call to this function'. level 1 is the C function that called the hook. 
    local info = debug.getinfo(2) 
    if info ~= nil and info.what == "Lua" then 
     local i, variables = 1, {""} 
     -- now run through all the local variables at this level of the lua stack 
     while true do 
      local name, value = debug.getlocal(2, i) 
      if name == nil then 
       break 
      end 
      -- this just skips unused variables 
      if name ~= "(*temporary)" then 
       variables[tostring(name)] = value 
      end 
      i = i + 1 
     end 
      -- this is what dumps info about a function thats been called 
     print((info.name or "unknown").. "(".. myUnpack(variables).. ")") 
    end 
end 

-- tell the debug library to call lua function 'hook 'every time a function call 
-- is made... 
debug.sethook(hook, "c") 

-- call a function to try it out... 
a_func("some string", 2012) 

これは出力になり:

a_func(asdf=2012, arg1=some string) 

あなたはかなり上品なことができますが、これは基本的にあなたが求めていることをする方法をカバーしています。

+0

元の投稿を誤解しました。彼は、その関数の外でその変数の名前を決定することを探しています(現在の回避策を参照してください)。つまり、呼び出し元がa_func(a、b)を実行した場合、 "asdf"と "arg1"を判別するのではなく、 "a"と "b"を探します。 –

+0

ahh、gotcha。それはスタックにたどり着いて、呼び出された関数に渡されたものと値が一致する範囲内の地方を把握しようとする可能性があります。しかし、デモのために非常に多くの仕事のように思えます... –

+0

あなたがそれを掲示すれば私はそれを投票するでしょう:) :) –

3

Luaは関数に引数を渡すためにどの変数(定数が使用されている可能性があるか)を判断できないため、PrintVariable(MyVariable)と言うことはできません。今

function PrintVariable(name) 
    -- default to showing the global with that name, if any 
    local value = _G[name] 

    -- see if we can find a local in the caller's scope with that name 
    for i=1,math.huge do 
    local localname, localvalue = debug.getlocal(2,i,1) 
    if not localname then 
     break -- no more locals to check 
    elseif localname == name then 
     value = localvalue 
    end 
    end 

    if value then 
    print(string.format("%s = %s", name, tostring(value))) 
    else 
    print(string.format("No variable named '%s' found.", name)) 
    end 
end 

はあなたが言うことができる:ただし、はPrintVariable('MyVariable')は、その名前を持つ呼び出し側のスコープ内のローカル変数を探すために、デバッグAPIを使用すると言うことができ

PrintVariable('MyVariable') 

この中にいる間"MyVariable = 4"と表示されます。


ない、あなた本当にはあなたが与えられた値を持つ変数に対して、発信者の地元の人々を確認することができ、引用符なしでこれをやりたいが、それは時折存在する場合、あなたに間違った変数名を与えるために起こっている場合指定された値で呼び出し元のスコープ内の複数の変数。ことで、ここにあなたがそれを行うだろう方法は次のとおりです。値4の呼び出し元の範囲内の他の変数があることが起こった場合は、PrintVariable(MyVariable)を言うことができる今

function PrintVariable(value) 
    local name 

    -- see if we can find a local in the caller's scope with the given value 
    for i=1,math.huge do 
    local localname, localvalue = debug.getlocal(2,i,1) 
    if not localname then 
     break 
    elseif localvalue == value then 
     name = localname 
    end 
    end 

    -- if we couldn't find a local, check globals 
    if not name then 
    for globalname, globalvalue in pairs(_G) do 
     if globalvalue == value then 
     name = globalname 
     end 
    end 
    end 

    if name then 
    print(string.format("%s = %s", name, tostring(value))) 
    else 
    print(string.format("No variable found for the value '%s'.", tostring(value))) 
    end 
end 

、しかし、それはMyVariable前に発生した、それはをですその印刷される変数名。

0

あなたはこのフォームを使用することができます。

local parms = { "MyVariable" } 

local function PrintVariable(vars) 
    print(parms[1]..": "..vars[1]) 
end 

local MyVariable = "bar" 

PrintVariable{MyVariable} 

与える:

MyVariable: bar 

をそれはジェネリックではありませんが、それは簡単です。このようにして、デバッグライブラリとロードストリングを回避します。あなたのエディタが良いものなら、それを行うためのマクロを書くことができます。

+0

あなたは同じことをリストfx(param、name、param 、name)、select()を使って名前を取得してください – sylvanaar

0

もう1つの解決策は、この施設を自分自身に追加することです。 Lua C APIとソースはかなりシンプルで拡張可能です。

私はあなたのプロジェクト/仕事のコンテキストを知らないのですが、独自のLuaビルドを作成/埋め込んでいる場合は、debugライブラリを拡張することができます。

Luaは参照によって値を渡しますが、これらの値に文字列名が含まれていればそれはわかりません。それはグローバルなので

_G["MyVariable"] = 4 

あなたの例では、値の宣言は同じです。もしそれがlocalと宣言されていれば、ここに述べられている他のもののように、debug.getlocal()によってそれらを列挙することができます。しかし、実際の参照文脈のC文脈においても、それは重要ではないかもしれない。

名前キーと値のペアで引数テーブルを拡張するdebug.getargumentinfo(...)を実装します。