lua-users home
lua-l archive

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


On Mon, 18 Aug 2014 13:18:38 +0200
Jan Behrens <jbe-lua-l@public-software-group.org> wrote:

> Consider a function printcsv, which accepts a sequence:
> 
> function printcsv(seq, sep)
>   sep = sep or ","
>   for i, v in ipairs(seq) do
>     if i > 1 then io.stdout:write(sep) end
>     io.stdout:write(tostring(v))
>   end
>   io.stdout:write("\n")
> end
> 
> Calling this with a raw table is pretty much forward:
> 
> printcsv{"a", "b", "c"}
> -- prints:
> -- a,b,c
> 
> printcsv({"a", "b", "c"}, "; ")
> -- prints:
> -- a; b; c

This just got me to the idea that if ipairs is made to accept
functions (or even iterator triplets), we could also implement
a generic concat:

==================================================
function string.concat(sep, ...)
  local t = {}
  for i, v in ipairs(...) do
    t[i] = tostring(v)
  end
  return table.concat(t, sep)
end
==================================================


Or optimized in C:

==================================================
int poweriterator_concat(lua_State *L) {
  int sep = 0;
  luaL_Buffer buf;
  luaL_checkany(L, 2);
  if (lua_isnoneornil(L, 1)) {
    lua_pushliteral(L, "");
    lua_replace(L, 1);
  } else {
    luaL_checkstring(L, 1);
  }
  lua_pushcfunction(L, poweriterator_ipairs);
  lua_insert(L, 2);
  lua_call(L, lua_gettop(L) - 2, 3);
  lua_pushnil(L);  // placeholder on stack at 5
  luaL_buffinit(L, &buf);
  while (1) {
    lua_pushvalue(L, 2);  // func
    lua_pushvalue(L, 3);  // state
    lua_pushvalue(L, 4);  // pos
    lua_call(L, 2, 2);
    if (lua_isnil(L, -2)) {
      lua_pop(L, 2);
      break;
    }
    lua_replace(L, 5);
    lua_replace(L, 4);
    if (sep) {
      lua_pushvalue(L, 1);
      luaL_addvalue(&buf);
    } else {
      sep = 1;
    }
    luaL_tolstring(L, 5, NULL);
    luaL_addvalue(&buf);
  }
  luaL_pushresult(&buf);
  return 1;
}
==================================================


This would give us much more power than table.concat:

(","):concat{"a", "b", "c"}
-- evaluates to: "a,b,c"

string.concat("; ", assert(io.open("testfile", "r")):lines())
-- evaluates to:
-- "This is line #1 of my testfile.; This is line #2 of my testfile."

string.concat(",", pairs{apple=true, pear=true})
-- evaluates to:
-- pear,apple
-- (ordering may vary)


I would find that really useful and pretty much straightforward.

I also don't see any negative side effects of making ipairs accept
functions or iterator triplets. Are there any?


I can understand that some of you don't miss generic iterators. But
they would allow for a new style of programming when using Lua.
As I said, I don't see any cons, only pros.

Can anyone come up with a real con?


Regards
Jan