[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: ipairs in Lua 5.3.0-alpha
- From: Jan Behrens <jbe-lua-l@...>
- Date: Tue, 19 Aug 2014 21:01:38 +0200
On Tue, 19 Aug 2014 19:15:47 +0200
Jan Behrens <jbe-lua-l@public-software-group.org> wrote:
> On Tue, 19 Aug 2014 18:01:00 +0200
> Jan Behrens <jbe-lua-l@public-software-group.org> wrote:
>
> > On Tue, 19 Aug 2014 15:38:58 +0200
> > Jan Behrens <jbe-lua-l@public-software-group.org> wrote:
> >
> > > extending ipairs in such way to accept functions (and possibly creating
> > > an easy to use API interface for ordinal iteration on functions AND
> > > tables) would encourage library programmers to create interfaces that
> > > do not distinguish between (function) iterators and (table) sequences.
> >
> > With an API interface, I mean something like this:
> >
> > #define luaL_geti(L, idx, i) ( \
> > (*(i))++, \
> > lua_type((L), (idx)) == LUA_TFUNCTION \
> > ? (lua_pushvalue((L), (idx)), lua_call((L), 0, 1)) \
> > : (lua_rawgeti((L), (idx), *(i))), \
> > lua_isnil((L), -1) \
> > ? (lua_pop((L), 1), LUA_TNIL) \
> > : lua_type((L), -1) \
> > )
> >
> > (This is just a draft. A real implementation might want to check
> > types for safety and/or respect the __call metamethod.)
>
> And here the "real" implementation (which is doing type-checks,
> respecting __call, and which does not evaluate lua_type for every
> iteration step):
>
> ==================================================
> #define LUA_ITERTYPE_FUNC 1
> #define LUA_ITERTYPE_META 2
> #define LUA_ITERTYPE_RAW 3
>
> typedef struct {
> lua_State *L;
> int itertype;
> int i;
> } luaL_Iterator;
>
> static void luaL_iterinit(lua_State *L, luaL_Iterator *iter, int idx) {
> iter->L = L;
> if (luaL_getmetafield(L, idx, "__call")) {
> iter->itertype = LUA_ITERTYPE_FUNC;
> } else if (lua_type(L, idx) == LUA_TFUNCTION) {
> lua_pushvalue(L, idx);
> iter->itertype = LUA_ITERTYPE_FUNC;
> } else {
> if (luaL_getmetafield(L, idx, "__index")) {
> lua_pop(L, 1);
> iter->itertype = LUA_ITERTYPE_META;
> } else {
> luaL_checktype(L, idx, LUA_TTABLE);
> iter->itertype = LUA_ITERTYPE_RAW;
> }
> lua_pushvalue(L, idx);
> }
> iter->i = 0;
> }
>
> static int luaL_iternext(luaL_Iterator *iter) {
> lua_State *L = iter->L;
> int i = ++iter->i;
> switch (iter->itertype) {
> case LUA_ITERTYPE_FUNC:
> lua_pushvalue(L, -1);
> lua_call(L, 0, 1);
> break;
> case LUA_ITERTYPE_META:
> lua_pushinteger(L, i);
> lua_gettable(L, -2);
> break;
> case LUA_ITERTYPE_RAW:
> lua_rawgeti(L, -1, i);
> break;
> default:
> abort(); // should not happen
> }
> if (lua_isnil(L, -1)) {
> lua_pop(L, 2);
> return 0;
> }
> return i;
> }
> ==================================================
>
>
> The invocation is a bit more clumsy (but avoids unnecessarily
> evaluating lua_type and luaL_getmetafield for every iteration step):
>
> static int printcsv(lua_State *L) {
> luaL_Iterator iter;
> int i;
> luaL_checkany(L, 1);
> for (luaL_iterinit(L, &iter, 1); (i = luaL_iternext(&iter)); lua_pop(L, 1)) {
> if (i > 1) fputs(",", stdout);
> fputs(lua_tostring(L, -1), stdout);
> }
> fputs("\n", stdout);
> return 0;
> }
>
>
> If that's too clumsy, one could also do something like this:
>
> #define luaL_loop(L, iter, idx, i) \
> for ( \
> luaL_iterinit((L), &(iter), (idx)); \
> (i = luaL_iternext(&(iter))); \
> lua_pop((L), 1) \
> )
Sorry, this should have been:
#define luaL_loop(L, iter, i, idx) \
for ( \
luaL_iterinit((L), (iter), (idx)); \
(*(i) = luaL_iternext(iter)); \
lua_pop((L), 1) \
)
for the example below to work.
>
> And then write:
>
> static int printcsv(lua_State *L) {
> luaL_Iterator iter;
> int i;
> luaL_checkany(L, 1);
> luaL_loop(L, &iter, &i, 1) {
> if (i > 1) fputs(",", stdout);
> fputs(lua_tostring(L, -1), stdout);
> }
> fputs("\n", stdout);
> return 0;
> }
>
>
> It still works fine:
>
> % lua52 -l printcsv
> Lua 5.2.3 Copyright (C) 1994-2013 Lua.org, PUC-Rio
> > printcsv{"a", "b", "c"}
> a,b,c
> > printcsv(assert(io.open("testfile", "r")):lines())
> line 1 in testfile,line 2 in testfile
>
>
> Regards
> Jan
>
- References:
- Re: ipairs in Lua 5.3.0-alpha, Jan Behrens
- Re: ipairs in Lua 5.3.0-alpha, Jan Behrens
- Re: ipairs in Lua 5.3.0-alpha, Jan Behrens
- Re: ipairs in Lua 5.3.0-alpha, Dirk Laurie
- Re: ipairs in Lua 5.3.0-alpha, Jan Behrens
- Re: ipairs in Lua 5.3.0-alpha, Jan Behrens
- Re: ipairs in Lua 5.3.0-alpha, Dirk Laurie
- Re: ipairs in Lua 5.3.0-alpha, Jan Behrens
- Re: ipairs in Lua 5.3.0-alpha, Dirk Laurie
- Re: ipairs in Lua 5.3.0-alpha, Jan Behrens
- Re: ipairs in Lua 5.3.0-alpha, Roberto Ierusalimschy
- Re: ipairs in Lua 5.3.0-alpha, Jan Behrens
- Re: ipairs in Lua 5.3.0-alpha, Jan Behrens
- Re: ipairs in Lua 5.3.0-alpha, Jan Behrens