lua-users home
lua-l archive

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

> From: Gregory Bonik <>
> > Practical example:
> >   Key1 = { first="John", last="Doe" }
> >   Key2 = { first="John", last="Doe" }
> > 
> > When using a key like the above for an table, currently Key1
> > and Key2 would identify different entries, i.e. are of no use.
> A function like Table.todata in not too hard to implement since you can
> use lua_topointer for tables, userdata, functions and threads.

I looked for such a function, but i did not find it...
I considered using 'tostring(tbl)' but the LUA API is so carefully
not to issue pointers, that i was uncertain how stable they might be.

> Now use intern_table to make keys:
> Key1 = intern_table { first="John", last="Doe" }
> Key2 = intern_table { first="John", last="Doe" }
> assert(Key1 == Key2)

Right, that's the point.

> Unfortunately, you cannot catch all modifications of tables in registry
> because the semantics of __newindex are so that an assignment t[v] = k
> ignores the metatable if there is already a key v in the table.

Yes, this could only be done by promissing not to change. A constant
table would /guarantee/ this. Perhaps it is so simple, and all what would
be needed is to set a bit in the table suppressing /any/ modifications
including resetting the bit. That would be a rather small and efficient patch.

The remainder could indeed be written in LUA itself, as the module i posted
demonstrates. Though the module is clearly not ideal in many respects,
it is a good proof of concept.

Earlier i searched the wiki and the web for composed keys in LUA but found
nothing. It is hard to understand, how people get along without ...

> Still, you can implement a consistency check function which traverses
> the registry and checks if tables really match their string representations.
> Alternatively, you could give up the idea of interned tables and just
> use table_to_string function to produce keys, e.g.
> Key1 = table_to_string { first="John", last="Doe" }

Problem with a string representation is, that it can grow exponentially,
when structure sharing comes into play. Try:

Key1 = table_to_string { first="John", last="Doe" }
Key2 = table_to_string { Key1, Key1 }
KeyN = table_to_string { Key(N-1), Key(N-1) }

You get a string of O(2^N) length, though having only N tables.

Additionally, one then has the key and the string, which is later
a pain to work with. With something like 'intern_table', the table
remains being the key.