lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]



What could be done though, is to address the userdata's / function's environment table via a similar mechanism as globals (LUA_GLOBALSINDEX) and upvalues (lua_upvalueindex(n)).

Let's say our userdata is at stack slot 1.

Now:
	lua_getfenv( L, 1 );	// [-1]: environment table (or nil?)
	lua_pushliteral( L, "monkey" );
	lua_gettable( L, 1 );	// [-1]: value 'env.table["monkey"]'
						// [-2]: environment table
	lua_remove(L,-2);

Then:
	lua_pushliteral( L, "monkey" );
	lua_gettable( L, lua_envindex(L,1) );

With functions, we could use a system just like 'lua_upvalueindex(n)', treating the function environment as an implicit upvalue (say, upvalue 0).

With userdata, we'd need to specify which userdata's environment we need.

Maybe the 'lua_getfenv()' and 'lua_setfenv()' functions could be removed, if all userdata and functions had the table automatically created, if needed. In this way, it would serve for making the API thinner.

- asko



Jerome Vuarand kirjoitti 7.7.2009 kello 12:49:

2009/7/7 Rob Kendrick <lua-l@nun.org.uk>:
On Mon, 6 Jul 2009 21:30:43 +0100
Peter Cawley <lua@corsix.org> wrote:

While I can't see how it makes any functional difference to how they
are done, it does mean there is only one interface the programmer
has to remember rather than one, as well as removing two functions
that pollute the global namespace.  It also feels more orthogonal
and consistent.

What am I missing?

Firstly, environment tables are per-function, whereas all functions
share a single metatable, so function environments could not be set
via metatable. Secondly, separating the environment from the metatable
allows for one to be per-instance and one to be per-class.

I can't quite think of a reason why you'd want the environment to be
per-instance, and not some of the other metatable fields, but OK.

For example your userdata1 may contain a pointer to another userdata2,
so to prevent userdata2 from being collected before userdata1 you may
want to keep a reference to userdata2 in some table associated with
userdata1. You can then use either the metatable or the environment of
userdata1 to store these per-instance references.

However, since some metamethods (eq, lt, le) only work if the
metatable is shared by several userdata (ie. per-class metatable), you
have to use the environment to hold per-instance data.