[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: '__iter', yet again!
- From: Ronald Lamprecht <R.Lamprecht@...>
- Date: Thu, 17 Dec 2009 00:09:29 +0100
Hi,
John Hind wrote:
I am trying to write an object oriented library in which you can have
objects for which the following is valid:
for v in obj do ... end
Using the __call metamethod you can easily get to:
for v in obj() do ... end
But the redundant parenthesis rankles.
In most cases you can simply eliminate the need of the parenthesis by
double indexing the container object. I noticed this usefull concept
when reengineering the Lua API for our project two years ago. I
implemented a set like container called "group" supporting joins,
intersections, etc. The for loop is as simple as:
for obj in group do obj:toggle() end
The implemention is very simple and does not require any Lua change at all.
In OO you can rely on objects having a unique id. You just need to store
the objects twice in your container - once at their regular index and
once at their id used as index. The "group" is in fact Lua table based
and stores the objects at standard numerical indices, which makes the
concepts implementation very straight forward.
The __call has no need to store the iteration state, as the last object
with its unique id fulfills this purpose:
static int iteratorGroup(lua_State *L) {
// generic for loop iterator function
// var_1 = _f(_s, _var) with _var == nil on first access, var_1 ==
nil on end
// on stack: group, _s, _var
if (!(is_group(L, 1)))
throwLuaError(L, "Group: iterator first arg not a group");
lua_getmetatable(L, 1);
int size = lua_objlen(L, -1);
if (lua_isnil(L, 3)) { // first iterator loop access
if (size == 0) { // an empty group
lua_pushnil(L);
return 1;
} else {
lua_rawgeti(L, -1, 1); // get the first object
return 1;
}
} else {
lua_pushvalue(L, 3); // copy last object as key
lua_rawget(L, -2); // get last index
int i = lua_tointeger(L, -1);
lua_rawgeti(L, -2, ++i); // get next object
return 1;
}
}
Be aware that the implementation depends on the containers index usage
and the object id's nature. But the concept can easily been modified for
other index and id types.
This implementation is up and running and is meanwhile being used by
multiple ten thousand lines of code.
you are
wrongfully introducing object oriented concepts in a language that is
not OO.
I was about to write this, but you were faster. Thanks,
I agree that in most cases it is preferable not to reveal underlying OO
technology in the Lua part to its full extend. A simple object based API
that hides complex concepts like inheritance can be more suitable.
Greets,
Ronald