[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: The purpose of LUA_ENVIRONINDEX pseudo index
- From: Luis Carvalho <carvalho@...>
- Date: Tue, 29 Aug 2006 12:29:22 -0400
On Tue, Aug 29, 2006 at 08:57:22AM +0200, Jose Luis Hidalgo Valiño wrote:
<snip>
> LUA_ENVIRONINDEX seems a way to hold data locally to a set of
> functions ( or only one ) but without loosing the possibility of
> access the full global environment (the thread environment) through
> LUA_GLOBALSINDEX.
I like to think of LUA_ENVIRONINDEX as a sort of "lua_upvalueindex(0)": it is
like a shared upvalue among all C functions that have the same environment. If
by locally you mean private, then a closure is more appropriate, as Mildred
stated. Check toy example below.
> In lua 5.1 lua_setfenv "changes" the behavior of LUA_ENVIRONINDEX or
> LUA_GLOBALSINDEX ? I'm not sure.
I don't understand what you mean, but since lua_setfenv changes the
environment of a function, thread or userdata, it affects LUA_ENVIRONINDEX for
C functions.
A simple example:
/* environ.c */
#include <lua.h>
#include <lauxlib.h>
static int environ_upv (lua_State *L) {
lua_Number e, u;
/* get environment data */
lua_rawgeti(L, LUA_ENVIRONINDEX, 1);
e = luaL_optnumber(L, -1, 0);
/* update environment */
lua_pushnumber(L, e+1);
lua_rawseti(L, LUA_ENVIRONINDEX, 1);
/* get closure data */
u = luaL_optnumber(L, lua_upvalueindex(1), 0);
/* update closure */
lua_pushnumber(L, u+1);
lua_replace(L, lua_upvalueindex(1));
lua_pushnumber(L, e);
lua_pushnumber(L, u);
return 2;
}
int luaopen_environ (lua_State *L) {
/* set current environment */
lua_createtable(L, 1, 0); /* environ table */
lua_pushnumber(L, 0);
lua_rawseti(L, -2, 1); /* environ[1] = 0 */
lua_replace(L, LUA_ENVIRONINDEX);
/* push closures with default environment (above) */
lua_pushnumber(L, 0);
lua_pushcclosure(L, environ_upv, 1);
lua_setfield(L, LUA_GLOBALSINDEX, "env1");
lua_pushnumber(L, 0);
lua_pushcclosure(L, environ_upv, 1);
lua_setfield(L, LUA_GLOBALSINDEX, "env2");
/* change environment using setfenv */
lua_pushnumber(L, 0);
lua_pushcclosure(L, environ_upv, 1);
lua_createtable(L, 1, 0); /* new environ table */
lua_pushnumber(L, 0);
lua_rawseti(L, -2, 1); /* environ[1] = 0 */
lua_setfenv(L, -2);
lua_setfield(L, LUA_GLOBALSINDEX, "env3");
return 0;
}
Lua 5.1 Copyright (C) 1994-2006 Lua.org, PUC-Rio
> require'environ'
> printupv = function(f) print(string.format('env: %d, upvalue: %d', f())) end
> printupv(env1)
env: 0, upvalue: 0
> printupv(env1)
env: 1, upvalue: 1
> printupv(env2)
env: 2, upvalue: 0
> printupv(env2)
env: 3, upvalue: 1
> printupv(env3)
env: 0, upvalue: 0
> printupv(env3)
env: 1, upvalue: 1
> printupv(env1)
env: 4, upvalue: 2
> printupv(env1)
env: 5, upvalue: 3
> printupv(env2)
env: 6, upvalue: 2
> printupv(env2)
env: 7, upvalue: 3
For more examples of LUA_ENVIRONINDEX, check liolib.c.
Cheers,
Luis.
--
A mathematician is a device for turning coffee into theorems.
-- P. Erdos
--
Luis Carvalho
Applied Math PhD Student - Brown University
PGP Key: E820854A <carvalho@dam.brown.edu>