Lua Basics: function environments and function parameters?

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Lua Basics: function environments and function parameters?

William Trenker
I've been experimenting with introspection in Lua (5.0.2).  If I
understand correctly, a function's parameters are not included in that
function's environment table.  For example:

------------------------ chunk -----------------------
function f(p)
    print(string.format("<%s>: p = %s", tostring(f),p))
    print(string.format("<%s>: getfenv(1).p = %s",tostring(f),
tostring(getfenv(1).p)))
end
f"I am P1"
------------------------- end chunk ---------------

prints:

<function: 0x80ebf90>: p = I am P1
<function: 0x80ebf90>: getfenv(1).p = nil

So I've followed the environment example in PIL and changed the
function to add the parameter into the function's environment:

------------------------ chunk -----------------------
function f(p)
    local env = getfenv(1)
    setmetatable(env, {__index=_G})
    env.p = p
    setfenv(1, env)
    print(string.format("<%s>: p = %s", tostring(f),p))
    print(string.format("<%s>: getfenv(1).p = %s",tostring(f),
tostring(getfenv(1).p)))
end
f"I am P1"
------------------------- end chunk ---------------

which now prints:

<function: 0x80e77c0>: p = I am P1
<function: 0x80e77c0>: getfenv(1).p = I am P1

What I find curious is what happens when I redfine the function in the
same chunk:

------------------------ chunk -----------------------
function f(p)  -- same as previous chunk
    local env = getfenv(1)
    setmetatable(env, {__index=_G})
    env.p = p
    setfenv(1, env)
    print(string.format("<%s>: p = %s", tostring(f),p))
    print(string.format("<%s>: getfenv(1).p = %s",tostring(f),
tostring(getfenv(1).p)))
end
f"I am P1"

function f(p)  -- redefine f in this chunk !!!!!
    print(string.format("<%s>: p = %s", tostring(f),p))
    print(string.format("<%s>: getfenv(1).p = %s",tostring(f),
tostring(getfenv(1).p)))
end
f"I am P2"
------------------------- end chunk ---------------

which prints:

<function: 0x80e77e0>: p = I am P1
<function: 0x80e77e0>: getfenv(1).p = I am P1
<function: 0x80ebfc8>: p = I am P2
<function: 0x80ebfc8>: getfenv(1).p = I am P1

Note that the last line prints "P1", not "P2". It appears that the
environment for the second definition of function f has the value of p
from the environment of the first definition of function f.  So, is
the function environment table for a function of a given name kept
around and reused if another function is defined with the same name?

Thanks for any insight,
Bill


Reply | Threaded
Open this post in threaded view
|

Re: Lua Basics: function environments and function parameters?

Rici Lake-2

On 25-Aug-05, at 3:33 PM, William Trenker wrote:

I've been experimenting with introspection in Lua (5.0.2).  If I
understand correctly, a function's parameters are not included in that
function's environment table.  For example:

That's correct. They are local variables.

What I find curious is what happens when I redfine the function in the
same chunk:


You've set p in the global environment.

The environment table is just a table; when a function closure is created, it is created with the same environment table as its creator (*not* a copy of the table):

------------------------ chunk -----------------------
function f(p)  -- same as previous chunk
    local env = getfenv(1)
-- env is now the global environment
    setmetatable(env, {__index=_G})
    env.p = p
-- so this sets p in the global environment
    setfenv(1, env)
    print(string.format("<%s>: p = %s", tostring(f),p))
    print(string.format("<%s>: getfenv(1).p = %s",tostring(f),
tostring(getfenv(1).p)))
end

What you probably wanted to do was:

function f(p)
  local env = {}  -- a new table
  setmetatable(env, {__index = _G})
    -- now the global environment is the "backup" for the new table
  env.p = p
  setfenv(1, env)
  -- now the function has a different environment table
  -- ...
end

The following is identical but maybe not so easy to read:

function f(p)
  setfenv(1, setmetatable({p = p}, {__index = _G}))
  -- ...
end