lua-users home
lua-l archive

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


On Tue, Sep 18, 2012 at 7:36 PM, Marc Lepage <mlepage@antimeta.com> wrote:
> Say I have objects with properties a, b, c etc.
>
> If it's a Plain Old Lua Table, then accesses of the properties can result in
> gets and sets:
>
>     o.a = o.b + o.c
>
> And I can use pairs to enumerate them:
>
>     for k, v in pairs(o) do
>         ... work with a, b, c
>     end
>
> But let's say I want to enforce a property, e.g. that a is always b + c. I
> could turn it into some function, such as:
>
>     o.getMagicValue() -- returns b + c
>
> but that makes it "special" compared to just o.a, which is nice for clients
> to use, and hides the fact that it's special.
>
> With a metatable, I can make an index for o.a return o.b + o.c. But that
> precludes using the metatable for another purpose, is slower than just
> accessing o.a as if it were a real field, and doesn't cope with o.a being an
> actual real field.
>
> I could have the metatable delegate to another hidden table for all storage.
> This means o never gets a real field, so it always works, but doesn't allow
> the pairs enumeration. Also, it is slower than direct field access, uses
> more memory (for the storage tables), and still presumes I don't want to use
> the metatable for another purpose.
>
> OK so far I understand all of this, from what I've read in the PiL book etc.
>
> What I'd like to know is if there are other options or patterns for
> implementing what are essentially objects that have a number of properties
> (fields), without wasting too much memory or performance, where I can do
> things like keep cached derived values and ensure they are kept up to date
> when properties are changed.
>
> Sort of like properties in C# or AS3 (which allow for get/set functions), or
> bean-style get/set functions in C++ (which can be inlined and optimized to
> simple struct accesses).
>
> I guess I'm wondering whether it's possible to have functions (code) that
> can run whenever a properties is set or get. Or something to that effect. At
> this point I'm leaning towards either requiring clients to use functions to
> perform sets (and let the perform direct gets if they wish).
>
> I'm wondering if I'm missing something in my thinking.

You are.

__index and __newindex only apply when the key doesn't already exist
in the table, so in practice it means that all undefined keys gain
property semantics. Since the lookup happens whether you've defined a
metatable or not, the performance hit for defined keys is negligible,
and the performance hit for properties is comparable to a function
call.

Just remember to use rawset and rawget if you need to bypass the
metamethods (for example, in the implementation of the metamethod
itself).

/s/ Adam