lua-users home
lua-l archive

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




On 16/07/16 09:33 PM, Tim Hill wrote:
On Jul 16, 2016, at 7:57 AM, Soni L. <fakedme@gmail.com> wrote:

— What is the type of the return value? It can’t be any existing Lua type, since this is *already* used as the identity of a value of that type. In other words, if __key returns (say) 100 as the key, then that will collide with using the number 100 in the same table. Not good. In fact, the only thing that __key could conceivably return would be another userdata pointer. And if you analyze this carefully, you will see if doesn’t buy you any functionality over what you already have.
Not good? If you have a bigint with value 100, any reasonable person would expect it to be compatible with a plain Lua number with value 100, just like how the plain Lua integer 100 is compatible with the plain Lua float 100.0. If Lua numbers have this property, why shouldn't other things?
Because the actual value that is stored as the key is coerced by Lua *before* it is stored as the key; so 100.0 is actually stored as 100. This is quite different to storing the key as a userdata but having an effective key that is a totally different type+value.

— If __key returns a different value when called multiple times on the same userdata, strange things will happen, possibly including Lua crashing, since this is unexpected behavior for any Lua value. Not good.
I can crash Lua with __gc and debug.getinfo. Your point? Locking it to userdata only significantly reduces that risk.
“I can crash Lua by doing X, so it’s ok if doing Y also crashes it” doesn’t seem a particularly good argument to me.

— If two distinct userdata’s return the same type+value for __key Lua will think they are the same value and bad things will happen if they are put in the same table, possibly crashing Lua. Not good.
This won't crash Lua.
A hypothetical design that is not yet implemented but you know it won’t have any problems. Hmmm. Let’s think a moment. I store normal table item t[10] = “ten”. Then someone stores t[u] = “uten” where u is a userdata whose __key metamethod returns 10. What happens? If the original store was into the array part, Lua can’t continue to use this because it has to allocate a cell to store the userdata pointer. In fact, it needs to evict the key+value from the array part and move to to the hash part, and then allocate THREE cells: one for the return value of __key, one for the userdata and one for the string value. And what about this code...?

It replaces t[10], obviously. Just like t[10.0] replaces t[10].

t[u] = nil

If __key() for u returns something other than 10, really surprising things are going to happen.

Like what?
As has been pointed out here many times, if a proposed feature is going to have a performance impact on the majority of users, it had better also have a benefit for the majority of users. Adding __key will certainly impact everyone (added logic in main code paths of the table module, extra cells to store user-returned keys etc). Will the majority also benefit? I don’t see that.

Added logic in the table module? Extra cells? What? We don't have extra cells for floats and we don't have added logic to handle floats, yet floats decay into integers if they have integral value, so why would __key need them?
And as others have noted, a better solution to the real problem of the OP is interning the bigint values so that two bigints are always the same userdata, which renders __key unnecessary.

And removes interoperability with plain Lua values. The point isn't to just access the same value from 2 different objects - this isn't some sort of __hash mechanism. The point is to interoperate with plain Lua values.

—Tim


Floats are a perfect example of the __key mechanism I proposed: they decay into integers if they have an integral value, otherwise they're used as-is.

--
Disclaimer: these emails may be made public at any given time, with or without reason. If you don't agree with this, DO NOT REPLY.