lua-users home
lua-l archive

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


Hi Pavol,

> The problem is of course that
> t={}
> t[ {1,2,3} ]=2
> print( t[ {1,2,3} ] )
> --> nil
>
> so I tried to overcome {1,2,3}~={1,2,3} with an  __eq field in a metatable:
> but to my surprise
> t={}
> t[ind(1,2,3)]=2
> print( t[ ind(1,2,3) ] )
> --> nil

There was a thread about this about a year ago, which you can read
http://lua-users.org/lists/lua-l/2005-06/msg00108.html . I had the
same problem that you are having.

Basically, Lua doesn't currently provide any way for objects to
override how they are hashed when used as keys in a table. So even
though the two {1, 2, 3} tables compare equal according to your
metamethod, the hash is still based on the table's addresses, so the
two tables are never even compared to one another.

There are a couple ways around this issue. One is to "stringify" the
keys, like you mention. This has the problem of requiring that the
keys be perfect string representations of the objects being used as
keys - which means they'll consume just as much memory (or more, since
they are in string form) as the actual objects, in addition to
requiring possibly expensive conversions between string and non-string
forms.

Another approach is to memoize the function which creates the objects
being used as keys such that all equal objects have the same memory
address.  See http://www.lua.org/pil/17.1.html for a discussion of
that. Sometimes works out nicely, other times it doesn't. Suppose
you'd like to use sets as keys for a table. You might build one of
these sets iteratively, adding to it in different parts of your
application. Finally you want to do a lookup of the set you've
created. I think this is a totally reasonable use case, but it's very
difficult to apply memoization in a case like this. (Of course, when
using mutable objects as keys in a table, care must be taken not to
modify the object once it has been inserted as a key.)

The last thing you can do is write your own table variant which checks
for a __hash metamethod (or whatever you'd like to call it) when using
tables as keys. This is what I ended up doing for the collections
framework I wrote:  http://sano.luaforge.net/  (In particular, check
out the documentation for HashMap:
http://sano.luaforge.net/documentation/HashMap.html ).

I'd love to see a future version of Lua have a __hash metamethod, I
really think it's the Right Thing to do. But when I brought this issue
up on the mailing list a year ago, it seemed like there was some
resistance from folks who thought that the above workarounds were
sufficient. I don't know what the Lua author's position is on all of
this.

Hope that helps.

Best,
Paul