lua-users home
lua-l archive

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


>> 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...?

t[u] = nil

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

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.

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.

—Tim