lua tables vs mutability

I’ve been battling a bug for a couple of days and this is a bit of a desperation call.

Does anyone know if you run into problems by using mutable objs as table keys in lua? In java for example you can have a problem with using multable keys of hashmaps because as the key mutates, so do their hash codes, and suddenly you can’t find them in the table anymore. I did a simple test and lua seems to avoid this problem, but I can’t find a resource online that asserts so.

Lua table keys are all either strings (which are immutable) or integers (again, immutable). Any variable used as a key is evaluated to one of those, and the result is used. So no - you’ll be fine.

I don’t think that’s right. You can use objects and even functions as keys. Or let me put this way, at least it doesn’t throw an error.

(by objects I mean codea classes which I guess really means tables. Functions might also be implemented as tables, not sure)

@ruilov: I could only find this quote on stack overflow re. using mutable objects as keys:

“In other languages, the hash value is more related to the objects ‘identity’, and not (necessarily) to the value. Thus, for a mutable object, the pointer could be used to start the hashing. Assuming, of course, that an object doesn’t move in memory (as some GC do). This is the approach used in Lua, for example. This makes a mutable object usable as a table key; but creates several (unpleasant) surprises for newbies.”

Sounds like it’s just hashed on the pointer. That seems to be the case from my experimenting on repl.it.

What’s the bug you’re trying to solve?

There’s also this section from the Lua manual on weak tables:

####2.10.2 - Weak Tables####

A weak table is a table whose elements are weak references. A weak reference is ignored by the garbage collector. In other words, if the only references to an object are weak references, then the garbage collector will collect this object.

A weak table can have weak keys, weak values, or both. A table with weak keys allows the collection of its keys, but prevents the collection of its values. A table with both weak keys and weak values allows the collection of both keys and values. In any case, if either the key or the value is collected, the whole pair is removed from the table. The weakness of a table is controlled by the __mode field of its metatable. If the __mode field is a string containing the character ‘k’, the keys in the table are weak. If __mode contains ‘v’, the values in the table are weak.

After you use a table as a metatable, you should not change the value of its __mode field. Otherwise, the weak behavior of the tables controlled by this metatable is undefined.

Yeah from what I can tell from lua source here

http://www.lua.org/source/5.1/ltable.c.html#mainposition

it seems to hash the pointer for everything but numbers/strings/booleans. Surprising that objects never move in memory though. I didn’t know that (not that I care)

Just found my bug actually! Sometimes you just need to put in words. It was hard because it was only triggered if the keys of my table where in one particular order within the table, so it only showed up randomly (based on the memory address of my variables I guess). If the keys were in this particular order, then by mistake I would change the table while iterating it, breaking my code

I actually thought it would use the __lt (less than) metamethod for key-lookup if it was defined, and the hash value if not. Surprising that it always uses the address.

ah you thought it binary searched it?

Anyway thanks for the help

how do you create a weak reference?

Yeah I guess because keys are anything, __lt doesn’t make sense. I was thinking it could binary search using the less than operator, but that only makes sense if the keys are homogenous. I have STL on the brain.

This section talks about how to create weak tables: http://www.lua.org/pil/17.html

wow, this is cool: “Lua’s garbage collector has no problems with cycles”

Well foo. So - what language am I thinking of then?

Perhaps more important - what kind of sick individual uses a function as a key to a table?

Bortels :slight_smile:

Fwiw the reason I’m doing it is because the keys of a table is a handy implementation of a “set” in lua. I want a “set” of functions. Instead of representing that as an array where I would have to check for duplicates each time I add a function to the set, instead I represent as a table where the functions are the keys.

@Simon, off topic but somehow this reminded me: equality doesn’t seem to be defined for colors, ie color(255,255,255,255)~=color(255,255,255,255). I’d be nice if it were defined.

Thanks for pointing that out. Color and vec3 need more metamethods. I’ll put it on the list.

Simon I take that back. Given that tables keep track of the pointer, not the value, equality defined by pointer seems better. Otherwise you’d end up with color1 == color2 but table[color1] ~= table[color2]