lua-users home
lua-l archive

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


On Sat, Jul 16, 2016 at 10:52 PM, Tim Hill <drtimhill@gmail.com> wrote:
> ok, I’ll explain this again. Ignoring for a moment the array part of a
> table, each table entry contains two items: a key and value. Both these are
> stored in “cells”, the Lua version of a typed value. Let’s focus on the key,
> since we are discussing this. For a value of 100.0, Lua first notices it’s
> an integral float, coerces that float value to 100 (an integer), and stores
> this value in the cell. So the key is a cell with a type of integer and a
> value of 100 (I’m simplifying a bit here). But when you add the __key
> metamethod, things are very different. First, Lua has to store the userdata
> reference (as otherwise it would be unreferenced and subject to garbage
> collection). However, you ALSO have to save the “key” (from __key) .. which
> is another type+value cell. So in this case the key part of the key+value
> entry in the table has TWO cells, not one: one for the userdata and one for
> whatever it is being indexed by; the return value of __key. So you have new
> code paths and extra data for each key+value entry in a table.
>
> The alternative of course is Lua calls __key every single time it needs to
> compare the key for a given table entry. Good luck with performance, And
> good luck if __key returns inconsistent values.

Hit send too soon.

It sounds like you're not understanding the suggestion at all. Lua
doesn't have to store the userdata reference at all, and it would be
perfectly fine if it got garbage collected, because the return value
of __key -- once it's been computed and stored in the table -- is
immutable, like I said in my last post (which should have been earlier
in this post), and is treated like any other table key (reference
identity for userdata and tables, value equality for everything else).

There are exactly two times when the __key metamethod gets called:

t[ud] = v  --> t[ud.__key()] = v
v = t[ud]  --> v = t[ud.__key()]

Of note, it does NOT get called in this situation:

k = ud.__key()
assert(t[k] == v) -- no __key used here!

But this absolutely ought to work.

Yes, there's ONE extra check made when accessing a table ("does the
key have a __key metamethod, yes or no?") so yes it does TECHNICALLY
make things more expensive, but this isn't anywhere close to a "good
luck with performance" kind of impact.

/s/ Adam