2012-05-05 38 views
2

的函數參數的名稱當調用像一個Lua函數獲取LUA

PrintMe(MyVariableName)

我想能夠實際打印「MyVariableName」,而不是它的價值(當然,對於演示目的)。

很明顯,我可以傳遞字符串,但需要額外的引號,我也想打印它的值。

例如,

MyVariable = 4 
PrintVariable(MyVariable) 

將打印 「MyVariable的是4」 或任何

我不希望有複製的名和變量像

PrintVariable(MyVariable, "MyVariable") 

,因爲這是不必要的複製。

lua可以處理嗎?

我現在正在做的是傳遞變量名引號和使用loadstring來獲取值,但我想只是通過變量直接沒有額外的不必要的引號(我認爲debug.getlocal做了,但它結束返回值而不是名稱)。


這裏是模擬例如

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) 

在這種情況下,所有3應打印同樣的事情。 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) 

爲了說明這一點,想象一下,如果我們做了:

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

PrintVariable(MyVariable) 

現在,如果你是Lua中,你會在最終的元數據變量附加什麼名字獲得通過的功能?是的,您可以使用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

啊,gotcha。如果你試圖找出堆棧中的哪些局部變量與傳遞給被調用函數的值相匹配,那麼這可能是可能的。似乎是一個演示很多工作,雖然... –

+0

如果你發佈它,我會投票... :) –

3

你不能說PrintVariable(MyVariable),因爲Lua沒有辦法確定哪個變量(如果有的話;可能已經使用了一個常量)被用來將參數傳遞給你的函數。但是,您可以PrintVariable('MyVariable')則使用的調試API來尋找呼叫者的範圍局部變量,它有一個名字:

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') 

雖然在本案件將打印「MyVariable = 4」。


不,如果你真的要做到這一點,不包括引號,你可以檢查呼叫者的當地人有一個提供的值的變量,但是這偶爾會給你錯誤的變量名,如果有調用者範圍中具有給定值的多個變量。隨着中說,這裏是你會怎麼做:

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 

現在你可以說PrintVariable(MyVariable),但如果碰巧在調用者與價值4範圍另一變量,它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

另一個可能的解決方案是添加此設施你自己。 Lua C API和源代碼非常簡單和可擴展。

我/我們不知道您的項目/工作環境,但是如果您正在製作/嵌入您自己的Lua版本,則可以使用某些功能來擴展debug庫。

Lua通過引用傳遞它的值,但如果這些值包含字符串名稱,並且如果容易訪問,則不確定。

在你的榜樣值聲明是一樣的:

_G["MyVariable"] = 4 

因爲它是全球性的。如果它被宣佈爲local那麼像其他人在這裏陳述的那樣,您可以通過debug.getlocal()列舉這些。但是,在實際參考環境的C語境中,它可能並不重要。

實現debug.getargumentinfo(...),它擴展了帶有名稱鍵和值對的參數表。