Lua - understanding setmetatable - lua

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?

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.

First, two important links:
metatables in Programming in Lua;
metatable events in the Lua wiki.
Now the answers:
t, the first parameter of the __index method in a metatable, refers to the table that has the metatable, here train_set. This parameter allows to reuse the same metatable for several tables.
__index is a special function inside metatables (look at the metatable events), that is called whenever a field in the metatabled table is accessed but missing. For instance, if train_set does not contain the key k and you read train_set.k, there will be a call to __index (train_set, "k") in its metatable.
From what i can infer from the code, the usage pattern in your example looks like local x = train_set [1] that will return a table containing { train_set.data[i], train_set.label[i] }.

Related

Lua overloads the operator to create a fake array

I want to create a 0-memory lua array that actually jumps to my custom function when I use operators like # [] on it
Any ideas on how to do this?
I want the user using this fake array to not perceive it as fake, it is worse than a normal array in terms of access speed, but has better memory performance
Lua implements something called metamethods (documentation)
Metamethods are functions which exist subsequently to a table and fire on certain operations such as indexing the array, reading missing indices, gathering the length of the array, or even math operations such as + - * /
-- Start by creating your array, and another for demonstration purposes
local object = {}
local demo = {1, 2, 3, 4}
-- Create a your metamethods contained in a table
local metamethods = {
__index = function(self, index) return demo[index] end;
__newindex = function(self, index, value) demo[index] = value end;
}
-- Lets print out what is in the object table for demonstration
print(object[1]) -- nil
print(object[2]) -- nil
print(object[3]) -- nil
print(object[4]) -- nil
-- Use the setmetatable(table a, table b) function to set the metamethods
-- stored in 'b' to 'a'
setmetatable(object, metamethods);
-- Lets print out what is in the object table for demonstration
print(object[1]) -- 1
print(object[2]) -- 2
print(object[3]) -- 3
print(object[4]) -- 4
Why does the above code work? When a metatable is set with the index __index (metamethods.__index), if the attached table's (object) is indexed and the key isn't present (nil), then it will call the specified function. In the __index function, it returns the demo's table with the index passed straight to it. So its as if: when you do object[1], you actually do demo[1] but with a metamethod's help of course. This effectively creates a proxy of sorts.
One cool and quick usage of setmetatable() is that it returns the value you pass as the first parameter (a table).
local object1 = setmetatable({}, { __index = function(self, i) return 1 end })
print(object1["a"]) -- 1
print(object2[321]) -- 1

Write-once table in lua?

I'd like to have a write-once table in Lua (specifically LuaJIT 2.0.3), so that:
local tbl = write_once_tbl()
tbl["a"] = 'foo'
tbl["b"] = 'bar'
tbl["a"] = 'baz' -- asserts false
Ideally, this would otherwise function like a regular table (pairs() and ipairs() work).
__newindex is basically the opposite of what I'd want for implementing this easily, and I am unaware of any techniques for making a proxy table pattern work with pairs() and ipairs().
You need to use a proxy table, that is, an empty table that catches all access to the actual table:
function write_once_tbl()
local T={}
return setmetatable({},{
__index=T,
__newindex=
function (t,k,v)
if T[k]==nil then
T[k]=v
else
error("table is write-once")
end
end,
__pairs= function (t) return pairs(T) end,
__ipairs= function (t) return ipairs(T) end,
})
end
Note that __pairs and __ipairs only work from Lua 5.2 onwards.

Whats the usage of metatables without metamethods?

I started learning Prototype-based programming in Lua. I wonder what's the usage of metatables without metamethods. There is a line in example below self.__index = self when I remove this line somevalue is not visible in my new object this is normal because I didn't use the metamethod __index. What's the usage of metatables then - to use metamethods only? Sorry for trivial question but this is really interesting, I know I can use getmetatable to check the metatable of some object. I need simple answer: There is no usage without metamethods or there is(if yes then what).
-- Example taken from the official documentation.
Account = { somevalue = 1 }
function Account:new (o)
o = o or {} -- create object if user does not provide one
setmetatable(o, self)
--self.__index = self
return o
end
a = Account:new()
print(a.somevalue) -- nil, so I can't use any features of the metatable till I use some metamethod?
By definition, metatables store metamethods. This does not mean that a metatable has to store only metamethods; several libraries use themselves as metatables.
A metatable is an ordinary Lua table. It only becomes the metatable of an object when you call setmetatable with it as its second argument.
You can also make keys or values or both weak with the __mode metatable key, which takes a string value and not a function (method)
Most metamethods are explained here:
Lua Manual: Metatables and Metamethods
Some Lua API functions also test for specific meta methods, like
__pairs - for pairs()
__ipairs - for ipairs()
__tostring - called by the tostring() function
__gc - for garbage collection
__metatable - read by the set/getmetatable functions (also a value)
If you search the manual file for the specific name including __ you will find the full definition and explanation, no use in repeating it here.
Well, yes, metatables store the metamethods of the object, and that's what they're used for, at least I haven't seen any other usecase.

In Lua, is there a function that given a function, it returns its name as a string?

Sorry if this is too obvious, but I am a total newcomer to lua, and I can't find it in the reference.
Is there a NAME_OF_FUNCTION function in Lua, that given a function gives me its name so that I can index a table with it? Reason I want this is that I want to do something like this:
local M = {}
local function export(...)
for x in ...
M[NAME_OF_FUNCTION(x)] = x
end
end
local function fun1(...)
...
end
local function fun2(...)
...
end
.
.
.
export(fun1, fun2, ...)
return M
There simply is no such function. I guess there is no such function, as functions are first class citizens. So a function is just a value like any other, referenced to by variable. Hence the NAME_OF_FUNCTION function wouldn't be very useful, as the same function can have many variable pointing to it, or none.
You could emulate one for global functions, or functions in a table by looping through the table (arbitrary or _G), checking if the value equals x. If so you have found the function name.
a=function() print"fun a" end
b=function() print"fun b" end
t={
a=a,
c=b
}
function NameOfFunctionIn(fun,t) --returns the name of a function pointed to by fun in table t
for k,v in pairs(t) do
if v==fun then return k end
end
end
print(NameOfFunctionIn(a,t)) -- prints a, in t
print(NameOfFunctionIn(b,t)) -- prints c
print(NameOfFunctionIn(b,_G)) -- prints b, because b in the global table is b. Kind of a NOOP here really.
Another approach would be to wrap functions in a table, and have a metatable set up that calls the function, like this:
fun1={
fun=function(self,...)
print("Hello from "..self.name)
print("Arguments received:")
for k,v in pairs{...} do print(k,v) end
end,
name="fun1"
}
fun_mt={
__call=function(t,...)
t.fun(t,...)
end,
__tostring=function(t)
return t.name
end
}
setmetatable(fun1,fun_mt)
fun1('foo')
print(fun1) -- or print(tostring(fun1))
This will be a bit slower than using bare functions because of the metatable lookup. And it will not prevent anyone from changing the name of the function in the state, changing the name of the function in the table containing it, changing the function, etc etc, so it's not tamper proof. You could also strip the tables of just by indexing like fun1.fun which might be good if you export it as a module, but you loose the naming and other tricks you could put into the metatable.
Technically this is possible, here's an implementation of the export() function:
function export(...)
local env = getfenv(2);
local funcs = {...};
for i=1, select("#", ...) do
local func = funcs[i];
for local_index = 1, math.huge do
local local_name, local_value = debug.getlocal(2, local_index);
if not local_name then
break;
end
if local_value == func then
env[local_name] = local_value;
break;
end
end
end
return env;
end
It uses the debug API, would require some changes for Lua 5.2, and finally I don't necessarily endorse it as a good way to write modules, I'm just answering the question quite literally.
Try this:
http://pgl.yoyo.org/luai/i/tostring
tostring( x ) should hopefully be what you are looking for
If I am not wrong (and I probably will, because I actually never programmed in Lua, just read a bunch of papers and articles), internally there is already a table with function names (like locals and globals in Python), so you should be able to perform a reverse-lookup to see what key matches a function reference.
Anyway, just speculating.
But the fact is that looking at your code, you already know the name of the functions, so you are free to construct the table. If you want to be less error prone, it would be easier to use the name of the function to get the function reference (with eval or something like that) than the other way around.

Meta metatables?

I'm trying to make an __index function in my table which can process ALL of the field it receives.. What I want to do is that if I call the table in the following way
mytable.str1.str2.str3
I should be able to return the table
{"str1", "str2", "str3"}
Note that str1,str2,str3 are undefined, they are just strings. I am not trying to create subtables str1, str2, I just want __index to see everything beyond the first period.
Unfortunately what I have seems that __index only captures str1, and complains that "attempt to index field 'str1' (a nil value)"
Anyone know how this can be done?
I'm not sure why you'd want to do this, but here's how you do it. The comments explain the trick, but basically you need a second metatable to handle the table that's returned from the first call to the __index metamethod.
If this isn't clear, let me know and I can explain in more detail.
-- This metatable appends the new key to itself, then returns itself
stringtablemeta = {}
function stringtablemeta.__index(self, key)
table.insert(self, key)
return self
end
-- In response to the question in the comments:
function stringtablemeta.__tostring(self)
local str = ""
for i, v in ipairs(self) do
if i > 1 then str = str .. "-" end
str = str .. v
end
return str
end
-- This metatable creates a new table, with stringmetatable as its metatable
mytablemeta = {}
function mytablemeta.__index(self, key)
local temp = { key }
setmetatable(temp, stringtablemeta)
return temp
end
-- set mytable to have mymetatable as it's metatable. This makes it so when
-- you index into it, it will call the mytablemeta.__index method.
--
-- That will return a talb with a single string, the key that was passed
-- in. that table will have it's own metatable, the stringmetatable, which
-- will cause it to append keys that are called on it with its own __index
-- metamethod
mytable = {}
setmetatable(mytable, mytablemeta)
test = mytable.str1.str2.str3
for k, v in pairs(test) do
print(k, v)
end
It can't. Not without having a metatable on each of those tables.
mytable is a table. str1 is a different table. So you can do the same thing by doing this:
local temp = mytable.str1
temp.str2.str3
And as far as Lua is concerned, these are equivalent. Therefore, the only way to know what was done at each stage is to give all of them a special metatable. How you concatenate the different values into a table is something you'll have to investigate on your own.
As Nicol said, you cannot do that directly in Lua. However, by returning specially crafted tables, you can achieve a similar result to what you want. Take a look at AutomagicTables at the Lua-users Wiki for inspiration.

Resources