Register forum user name Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.

Due to spam on this forum, all posts now need moderator approval.

 Entire forum ➜ SMAUG ➜ Lua ➜ Keeping a list of known fields

Keeping a list of known fields

It is now over 60 days since the last post. This thread is closed.     Refresh page


Posted by David Haley   USA  (3,881 posts)  Bio
Date Sat 06 Sep 2008 03:52 AM (UTC)
Message
I have an object, the details of which aren't really important (it's a binding for characters), represented by a table in Lua-space. This object has many fields. Lua has no compile-time checking for whether or not a field exists, so there is no way for me to know if I made a typo when I access a field in the code. The best I can do, if I want to be sure that I'm accessing a field that's actually valid, is to have runtime checks against a list of known fields. Currently I'm doing this:

local priv_fields = 
    set.new({
        "inputStatus", "inputCoroutine", "inputCommand",
        "sendPrompt",
    })

function __index(actor, key)
    -- is this a known field?
    if priv_fields:contains(key) then
        return actor.__private[key]
    end

    -- is it a module field?
    if _M[key] then
        return _M[key]
    end

    -- we don't know what it is... ack
    error("unknown actor field/method: " .. key)
end

function __newindex(actor, key, val)
    -- if it's a known field, we can set it
    if priv_fields:member(key) then
        actor.__private[key] = val
        return
    end

    -- can't assign to anything else...
    error("can't assign to actor field: " .. key)
end


Every access to a field entails the indirection of the metatable. Admittedly, this is not very expensive: at worse it is just two table lookups. (Well, set:contains entails a function call that then does a table lookup. So that's two table lookups and a function call.)

Is this a reasonable solution? What are other people doing? Not having any kind of compile-time verification kind of bothers me, and implementing (or finding/figuring out somebody else's) static analysis is not something I really have time to do. I'm not happy with the runtime checks (their usefulness is directly proportional to the code's frequency of execution) but it's the best I'm seeing at the moment.

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
Top

Posted by Nick Gammon   Australia  (23,140 posts)  Bio   Forum Administrator
Date Reply #1 on Sat 06 Sep 2008 04:08 AM (UTC)
Message
Can't you just use __index without the hidden table? That way, an attempt to get a non-existent field will involve the check, but if the field has data in it, you assume it is good.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by David Haley   USA  (3,881 posts)  Bio
Date Reply #2 on Sat 06 Sep 2008 04:15 AM (UTC)
Message
Do you mean only use __newindex? I want an error to be triggered when an unknown is either accessed or created. Doesn't that mean I need to use both?

Or did you mean that __index can see directly if the field exists in the actor? Something like this:


function __index(actor, key)
    -- is this a known field?
    if actor[key] then
        return actor.__private[key]
    end

    -- is it a module field?
    if _M[key] then
        return _M[key]
    end

    -- we don't know what it is... ack
    error("unknown actor field/method: " .. key)
end


The problem here is that some fields might legitimately be nil-valued, but still be known fields. How would you get around that?

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


9,863 views.

It is now over 60 days since the last post. This thread is closed.     Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.