lua-users home
lua-l archive

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


Hi,

I decided to put together a simple tuple implementation based on previous
discussions in the list (check attachment). It contains a constructor, tuple,
and an iterator, ituple. Some usage examples:

$ lua
Lua 5.1.1  Copyright (C) 1994-2006 Lua.org, PUC-Rio
> require"tuple"
> t = tuple(10,math.pi,nil,{},nil,"foo",math.sin)
> print(t())
10      3.1415926535898 nil     table: 0x80828f8        nil     foo     function: 0x806e928
> print(t(5))
nil     foo     function: 0x806e928
> print(t(2,4))
3.1415926535898 nil     table: 0x80828f8
> print(t(0), #t, t[2])
7       7       3.1415926535898
> f = function(arg) for i,v in ituple(arg) do print(i,v) end return tuple(arg()) end
> x = f(t)
1       10
2       3.1415926535898
3       nil
4       table: 0x80828f8
5       nil
6       foo
7       function: 0x806e928
> print(x())
10      3.1415926535898 nil     table: 0x80828f8        nil     foo     function: 0x806e928

I've also got a list implementation with some functional facilities based on
tuples, but that's offtopic. :)

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>
/*
 * tuple.c v0.1
 * Simple functional tuple implementation with metatables:
 * This is similar to Roberto Ierusalimschy's tuples in PiL, but draws
 * inspiration from Rici Lake's suggestions in lua-l.
 *
 * This code is in public domain.
*/

#include <lua.h>
#include <lauxlib.h>

#define istuple(n) (lua_tocfunction(L, (n)) == tupleF)
#define tuple_validindex(n) lua_type(L, lua_upvalueindex((n))) != LUA_TNONE
#define tuple_getindex(n) lua_pushinteger(L, (n)); lua_call(L, 1, 1);
#define tuple_getlength() tuple_getindex(0)

/* functional tuple */
static int tupleF (lua_State *L) {
  int i, j, n;
  i = luaL_opt(L, lua_tointeger, 1, 1);
  if (i == 0) { /* length? */
    for (n = 1; tuple_validindex(n); n++) ;
    lua_pushinteger(L, n - 1);
    return 1;
  }
  /* tuple slicing */
  j = luaL_opt(L, lua_tointeger, 2, 0);
  if (j == 0) {
    for (n = i; tuple_validindex(n); n++)
      lua_pushvalue(L, lua_upvalueindex(n));
  }
  else {
    for (n = i; tuple_validindex(n) && n <= j; n++)
      lua_pushvalue(L, lua_upvalueindex(n));
  }
  return n - i;
}

/* methods */
static int tuple_index (lua_State *L) {
  if (istuple(1)) {
    lua_call(L, 1, 1);
    return 1;
  }
  return 0;
}

static int tuple_len (lua_State *L) {
  if (istuple(1)) {
    lua_settop(L, 1);
    tuple_getlength();
    return 1;
  }
  return 0;
}

static int newtuple (lua_State *L) {
  int n = lua_gettop(L);
  luaL_argcheck(L, n <= LUA_MINSTACK, n, "too many elements");
  lua_pushcclosure(L, tupleF, n);
  return 1;
}

static int itupleaux (lua_State *L) {
  int n, i = lua_tointeger(L, 2) + 1;
  lua_pop(L, 1);
  lua_pushvalue(L, 1); /* tuple */
  tuple_getlength();
  n = lua_tointeger(L, -1);
  lua_pop(L, 1);
  if (i <= n) {
    lua_pushinteger(L, i);
    lua_pushvalue(L, 1); /* tuple */
    tuple_getindex(i);
    return 2;
  }
  return 0;
}

static int ituple (lua_State *L) {
  lua_settop(L, 1);
  if (!istuple(1)) luaL_typerror(L, 1, "tuple");
  lua_pushcfunction(L, itupleaux);
  lua_insert(L, -2);
  lua_pushinteger(L, 0);
  return 3;
}

static const luaL_reg tuple_mt[] = {
  {"__index", tuple_index},
  {"__len", tuple_len},
  {NULL, NULL}
};

int luaopen_tuple (lua_State *L) {
  lua_pushcfunction(L, newtuple);
  lua_newtable(L); /* metatable */
  luaL_register(L, NULL, tuple_mt);
  lua_setmetatable(L, -2);
  lua_pushvalue(L, -1);
  lua_setglobal(L, "tuple");
  lua_pushcfunction(L, ituple);
  lua_setglobal(L, "ituple");
  return 1;
}