• Subject: Re: Lightweight Lua Enumerations
• From: Rici Lake <lua@...>
• Date: Wed, 27 Jun 2007 19:06:58 -0500

```
On 27-Jun-07, at 6:09 PM, Gavin Kistner wrote:

```
```What do _you_ do when you need a simple, lightweight way to create some
unique values?
```
```
I use simple lower case strings, unless a better solution
occurs to me. In your example, I would might use "good", "sin",
"cos" and "sin".

Having said that, I might well choose to use math.sin and math.cos
for the operation, if those were appropriate. For example,
rather than using an enumeration of "BlendType"'s, I would be
tempted to use the actual blending functions.

```
```Do you worry about cross-enumeration comparisons?
```
```
No. I figure that it's about the same as using the same name
for two completely unrelated methods in unrelated classes.
(Shape:draw() versus Sheriff:draw() would be the classic example).

C enumerations.The validity of the string is checked
by looking up the C enumeration in a table attached as an
upvalue to the C closure, which is reasonably simple and fast:

static int foo_set_op (lua_State *L) {
lua_Integer op = 0;
Foo *self = check_self(L);
if (lua_type(L, 2) == LUA_TSTRING) {
lua_rawget(L, lua_upvalueindex(1));
op = lua_tointeger(L, -1);
if (op != 0 || lua_type(L, -1) == LUA_TNUMBER) {
self->op = op;
return 0;
}
}
luaL_typerror(L, 2, "Operation");
return 0;
}

static int foo_get_op (lua_State *L) {
Foo *self = check_self(L);
lua_rawgeti(L, lua_upvalueindex(1), self->op);
return 1;
}

The same table is used for both functions; it has integer keys
which map to strings, and string keys which map to integers.

check_self, by the way, is implemented by setting the environment
table of the closures to the metatable for the object type, so it
can be quite general:

void *check_self (lua_State *L) {
if (lua_getmetatable(L, 1) && lua_rawequal(L, -1, LUA_ENVIRONINDEX)) {
lua_pop(L, 1);
return lua_touserdata(L, 1);
}
else {
lua_getfield(L, LUA_ENVIRONINDEX, "__typename");
luaL_typerror(L, 1, lua_tostring(L, -1));
return 0;
}
}

The enumeration checking code above can be refactored for convenience
as well.

```