Master tables

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
_pie
Prole
Posts: 2
Joined: Wed Jan 13, 2021 5:12 am

Master tables

Post by _pie » Wed Jan 13, 2021 5:50 am

I am Pretty New to meta-tables and wonder why this doesn't work can anyone help me solve this small problem. also searched web and did not find anything related to it.
Goal is to have one Meta-table and have multiple tables added to the master table from different .lua files
can this be possible?
Attachments
MasterTable.love
(894 Bytes) Downloaded 61 times

MrFariator
Party member
Posts: 213
Joined: Wed Oct 05, 2016 11:53 am

Re: Master tables

Post by MrFariator » Wed Jan 13, 2021 5:22 pm

There's two ways to implementing the __index metamethod. Lets cover the function approach first: When you try to fetch a value from a table by key that does not exist, and the table's metatable has __index defined and it is a function, this allows you to basically "redirect" the search, or create other mechanisms (eq. raising an error). The __index method receives two values: the table the metatable is attached to, as well as the key that is trying to be accessed.

If you modify your master.lua like the following, it should work:

Code: Select all

function master:new()
  local obj = {
      dollar=100,
  }
  -- create a child table that can be accessed in the master table, you can go other ways about this
  obj.child = child:new()
  
  setmetatable (
    obj, 
    { 
      -- define the function, this naively assumes that any key that is not present in 'master' will be available in 'child'
      __index = function (myTable, key) 
        return myTable.child[key]
      end
    }
  )
  __call = function(master, child) end
  return obj
end

p=master:new()
print(p.dollar) -- prints 100
print(p.dime) -- prints 10
The alternative is assigning a table to __index. This basically gives the table a fallback table to check when attempting to access a key that does not exist. You simply pass a candidate table like so:

Code: Select all

function master:new()
  local obj = {
      dollar=100,
  }
  local childObj = child:new()
  setmetatable (
    obj, 
    { 
      __index = childObj -- now when accessing a non-existant key in the master table, the child table gets checked
    }
  )
  __call = function(master, child) end
  return obj
end

p=master:new()
print(p.dollar) -- prints 100
print(p.dime) -- prints 10
And with this table approach, if the child table defines another table via its __index metamethod, this chain of checks will continue further and further.

If you want to bypass the __index metamethod at any time, you can use rawget(table,key) and rawset(table,key) functions.

For more information, this is the general article I've used to look up metamethods whenever I have needed a refresher. Keep in mind not all metamethods listed in that article are available in the version of lua (or luajit, rather) love2d uses.

User avatar
pgimeno
Party member
Posts: 2483
Joined: Sun Oct 18, 2015 2:58 pm

Re: Master tables

Post by pgimeno » Wed Jan 13, 2021 5:33 pm

MrFariator wrote:
Wed Jan 13, 2021 5:22 pm

Code: Select all

  __call = function(master, child) end
Are you sure that's correct? You're defining __call as a global. I haven't seen the OP's code though, so maybe it makes more sense in the context of the program.

MrFariator
Party member
Posts: 213
Joined: Wed Oct 05, 2016 11:53 am

Re: Master tables

Post by MrFariator » Wed Jan 13, 2021 5:36 pm

Oh, oops, yes, that is a mistake that is also present in the original code. Somehow slipped past me; it obviously should be put inside the metatable within the setmetatable call. I am going to assume OP first wanted to get the __index working, and had this __call line in there doing nothing.

_pie
Prole
Posts: 2
Joined: Wed Jan 13, 2021 5:12 am

Re: Master tables

Post by _pie » Thu Jan 14, 2021 3:29 pm

Oh its not easy to use metatables the way I thought!
Do you think this approach will not work in large projects?
or will it be confuse even to debug?
I am trying to learn how to use metatables not just on one file
I have search how to use it but fail ,I don't see tutorials that explain how to use it in more files.lua also thanks for the link.

MrFariator
Party member
Posts: 213
Joined: Wed Oct 05, 2016 11:53 am

Re: Master tables

Post by MrFariator » Thu Jan 14, 2021 4:15 pm

Can this approach work in larger projects? Sure, I don't see why not. Of course, be mindful of the potential performance penalties that might occur due to the extra added hoops for simple table lookups. Here it's neglible, but with more complex __index chaining it could get costly in performance critical code. One way or the other though, yes, it is bound to get confusing to debug - and if I may be frank I'm not even sure what your intended goal is here.

Can you maybe provide some context for what you're trying to do? Maybe this code might make more sense with larger objects than just simple tables containing a single value individually, like in the master and child examples provided.

User avatar
pgimeno
Party member
Posts: 2483
Joined: Sun Oct 18, 2015 2:58 pm

Re: Master tables

Post by pgimeno » Fri Jan 15, 2021 1:34 pm

I've written sort of a tutorial on metatables: https://codeberg.org/pgimeno/Gists/src/ ... e-tutorial

It covers most of the fine details of how metatables work, including some advanced aspects.

Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 39 guests