lua-users home
lua-l archive

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



hmmph. I should have email this to the list, instead of just to Phil.

Roberto is right that l_push ought to check for overflow... I forgot about the possibility of open calls which might increase the arg list beyond the capacity of a cclosure (which ought to be bigger, anyway).
I would like, however, to note the simplicity derivable from the use of lua_pushupvalues() :)

The curious list iterator allow garbage collection to occur during the traversal of a list; the whole apparatus was carefully designed to allow for iteration. head, tail and emptyp are simply for decoration.
Here it is, in its entirety:

function head(list) local _, rv = list(); return rv end
function tail(list) return (list()) end
function emptyp(list) return (list()) end -- !
do
  local function auxNext(_, list) return list() end
  function listEach(list) return auxNext, nil, list end
end

-- here is the C part. Charmingly simple, no?

static int l_tuple(lua_State *L) {
  return lua_pushupvalues(L);
}

static int l_push(lua_State *L) {
  lua_pushcclosure(L, l_tuple, lua_gettop(L));
  return 1;
}

extern int luaopen_listlib(lua_State *L) {
  lua_pushliteral(L, "push");
  lua_pushcclosure(L, l_push, 0);
  lua_settable(L, LUA_GLOBALSINDEX);
  lua_pushliteral(L, "null");
  lua_pushcclosure(L, l_tuple, 0);
  lua_settable(L, LUA_GLOBALSINDEX);
  return 0;
}

The interesting thing about this implementation, other than the fact that it puts the cdr before the car (actually, that mirrors the original PDP-6 implementation iirc), is that a cell can have any number of values. So you could use it, for example, to collect a list of key=value attributions. (Of course, as usual with lists, you would have to reverse after construction.)