Search code examples
lualua-tabletorchmetatable

Lua - understanding setmetatable


I am trying to build a CNN using Torch 7. I am very new to Lua. I was trying to follow this link. I encountered something called setmetatable in the following code block:

setmetatable(train_set, 
{
  __index = function(t, i) 
    return {t.data[i], t.label[i]}
  end
});

I understand that the second argument acts as the metatable for the table train_set.

1) Is t the metatable or is t just another name for train_set?

2) Whenever a function is used against __index, does the interpreter assume the first argument (t) to be a table (or metatable, depending on answer to first question)? And is the second argument always the key or index?

3) My understanding is that if I use train_set.data[1], it will invoke the __index. The answer here says that __index is invoked when key does not exist in the table. But is t.data[1] same as train_set.data[1]? If so, how does the interpreter know that?


Solution

  • setmetatable(train_set, 
    {
      __index = function(t, i) 
        return {t.data[i], t.label[i]}
      end
    })
    

    Here we have some table named train_set. With this function call we set its metatable to

     {
      __index = function(t, i) 
          return {t.data[i], t.label[i]}
      end
     }
    

    This is an anonymous table. If this is hard to read for you, you could also write:

    local my_metatable = {
      __index = function(t, i) 
         return {t.data[i], t.label[i]}
      end
    }
    setmetatable(train_set, my_metatable)
    

    Inside that metatable we implement the metamethod __index. By doing this we tell Lua what to do when someone is indexing a field in train_set that does not exist.

    So when we ask Lua to give us the value stored in train_set[4] for example and train_set[4] is nil, Lua will go check if __index is implemented. If so it will call __index(train_set, 4) and give you its return value or otherwise return nil So the interpreter knows that t.data[1] is the same as train_set.data[1], because he's the one who put train_set into __index.

    So when you implement __index it will always be called using the indexed table as first and the index as second argument.