33

I know how to print "all" global variables using the following code

for k,v in pairs(_G) do
 print("Global key", k, "value", v)
end

So my question is how to do that for all variables that are accessible from the currently executing function, something that can do what locals() does for Python.

asked May 14, 2010 at 13:46

5 Answers 5

42

Here is an implementation of a locals() function. It will return a table of locals from the calling scope:

function locals()
 local variables = {}
 local idx = 1
 while true do
 local ln, lv = debug.getlocal(2, idx)
 if ln ~= nil then
 variables[ln] = lv
 else
 break
 end
 idx = 1 + idx
 end
 return variables
end

Notice that in the lua REPL, each line is a separate chunk with separate locals. Also, internal variables are returned (names start with '(' if you want to remove them):

> local a = 2; for x, v in pairs(locals()) do print(x, v) end
a 2
(*temporary) function: 0x10359b38

Thanks for the accept. You have unlocked the last piece of the puzzle! ;-)

Upvalues are local variables from outer scopes, that are used in the current function. They are neither in _G nor in locals()

function upvalues()
 local variables = {}
 local idx = 1
 local func = debug.getinfo(2, "f").func
 while true do
 local ln, lv = debug.getupvalue(func, idx)
 if ln ~= nil then
 variables[ln] = lv
 else
 break
 end
 idx = 1 + idx
 end
 return variables
end

Example (notice you have to use a for it to show up):

> local a= 2; function f() local b = a; for x,v in pairs(upvalues()) do print(x,v) end end; f()
a 2
answered May 14, 2010 at 15:38
Sign up to request clarification or add additional context in comments.

3 Comments

Why it stores pairs in (*temporary)?
happy, it's a Lua implementation thing
Same thing without the (*temporary): function locals() local variables = {} local idx = 1 while true do local ln, lv = debug.getlocal(2, idx) if ln == nil then return variables end variables[ln] = lv idx = 1 + idx end end
8

Use debug.getlocal.

answered May 14, 2010 at 14:43

2 Comments

It's too short to be useful for someone hitting the web with the question I asked. But thanks anyway!
man, the 2010s sure were a different time....... a better time.......
4

See debug.getlocal:

local foobar = 1
local i = 0
repeat
 local k, v = debug.getlocal(1, i)
 if k then
 print(k, v)
 i = i + 1
 end
until nil == k

Output:

foobar 1
i 2
answered May 14, 2010 at 14:45

5 Comments

Did you run the code you pasted? I'm running it using Lua 5.1.4 on Ubuntu and it does not print anything at all. I saved the code on a file and executed in the console with lua test.lua. Am I missing something?
Yes, I ran it on Ubuntu 10.04 with the same version of Lua.
Did you place it in a file as is or wrap it in a function call?
I thought any chunk would do it, and a file is a chunk, isn't it? Anyway, I just wrapped it in a function to no avail either :( I'm on Ubuntu 9.04 (Jaunty).
shouldn't the last statement be k == nil instead? or simpler not k
4

The problem with Judge Maygarden's loop version above is simply local i = 0. It does nothing because the first indexed with '0' will always return nil.

Remember Lua indexes by default start with '1', not '0' like C/C++. You can use '0' for an index with your own types of course, but the default functions are expecting the default of '1' as the first index.

Just change it to local i = 1 and his loop will work fine.

RAS
8,15017 gold badges68 silver badges86 bronze badges
answered Jun 25, 2012 at 0:11

Comments

0

You can use getfenv to get a local environment.

getfenv ([f]) Returns the current environment in use by the function. f can be a Lua function or a number that specifies the function at that stack level: Level 1 is the function calling getfenv. If the given function is not a Lua function, or if f is 0, getfenv returns the global environment. The default for f is 1.

Edit: sorry, I was wrong.

I just checked Lua source code. debug.getlocal() is the only way to get the local variables.
Lua uses an internal Proto structure and doesn't give us access to that.
(Proto holds local properties plus a parent Proto reference. Iterating function's Proto, by using getfenv,
we also iterate inherited properties, not what we wanted)

Users can define their Proto s either with environments and the set/getfenv functions or by using metatables.

answered May 14, 2010 at 14:00

3 Comments

Your solution did not work. The following does not print foobar: local foobar = 1; for k,v in pairs(getfenv()) do print(k, v) end Am I missing something?
I believe getfenv will only show globals withing the given scope/environment.
@Judge, yes, but we can replace function's env with some other. As I discovered, when we iterate over an env we also iterate over the inherited chain of internal prototypes. We cannot really get local declarations unless we use the built-in debug.getlocal.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.