Lua - set table(anonymous) value - lua

return{
initime = 1;
isneed= true; -- need to modify
testfn=function()
isneed = false; ---how to modify the "isneed" value?
end
}
i wanna modify the isneed's value,i have try like this
local testdata;
testdata={
initime = 1;
isneed= true;
testfn=function()
testdata.isneed = false;
end
}
return testdata;
but the code that i dont want,i think have another way to set the value.

Building on #luther's comment, the code you have in your second example should work.
local testdata = {
initime = 1,
isneed = true,
testfn = function()
testdata.isneed = false
return
end
}
print(testdata.isneed)
testdata.testfn()
print(test.data.isneed)
This should output the following:
true
false
Alternatively, if you wanted to get a little fancier, you could use a metatable to overload the call operator for your table testdata:
local testdata = {
initime = 1,
isneed = true,
testfn = function()
testdata.isneed = false
return
end
}
testdata = setmetatable(testdata, {
__call = function(self)
return self.testfn()
end
})
print(testdata.isneed)
testdata()
print(testdata.isneed)
This example's output is equivalent to the above output. Depending on what exactly you wish to accomplish with your code, overloading the call operator with a metatable could offer you some more flexibility. Using this approach, you could change your code slightly like this, making use of the self parameter in the __call function:
local testdata = setmetatable({initime = 1, isneed = true}, {
__call = function(self)
self.isneed = false
return
end
})
print(testdata.isneed)
testdata()
print(testdata.isneed)
This will produce the same output as the first example.

Related

Call an object method from a string

I have a main loop in my lua script, and i am including 2 objects like this:
local Menu = require("menu")
local InputHandler = require("inputhandler")
Here are the scripts for each object:
menu.lua
Menu = {
Active = false,
Initialise = function(self)
end,
ToggleMenu = function(self)
self.Active = not self.Active
print(self.Active)
end
}
return Menu
and inputhandler.lua
InputHandler = {
KeyBinds = {
q = { scancode = 16, bind = "q", action = "Menu:ToggleMenu" }
},
RunKeyAction = function (self, key)
for k, v in pairs(self.KeyBinds) do
if (v.bind == key) then
_G[v.action]()
end
end
end
}
return InputHandler
Basically I am trying to map keyboard keys to various functions within my script, so when someone presses "Q", it will run the method associated with that key.
So if I do something like this:
InputHandler:RunKeyAction("q")
It will run this method:
Menu:ToggleMenu()
When I run this script as it is now, I get this error:
lua: ./classes//inputhandler.lua:8: attempt to call field '?' (a nil value)
stack traceback:
./classes//inputhandler.lua:8: in function 'RunKeyAction'
[string "<eval>"]:20: in main chunk
Can anyone please tell me that correct way of doing this?
Thank you for reading
Use
q = { scancode = 16, bind = "q", action = Menu.ToggleMenu }
and
v:action()

How to call a library function by its name and setting it's parameters

I have a library functions defined like that in my C code :
static const struct luaL_reg SelSurfaceLib [] = {
{"CapabilityConst", CapabilityConst},
{"create", createsurface},
{NULL, NULL}
};
static const struct luaL_reg SelSurfaceM [] = {
{"Release", SurfaceRelease},
{"GetPosition", SurfaceGetPosition},
{"clone", SurfaceClone},
{"restore", SurfaceRestore},
{NULL, NULL}
};
void _include_SelSurface( lua_State *L ){
luaL_newmetatable(L, "SelSurface");
lua_pushstring(L, "__index");
lua_pushvalue(L, -2);
lua_settable(L, -3); /* metatable.__index = metatable */
luaL_register(L, NULL, SelSurfaceM);
luaL_register(L,"SelSurface", SelSurfaceLib);
}
And I can use it with this Lua code :
local sub = SelSurface.create()
local x,y = sub:GetPosition()
...
Now, my difficult issue : I'm using follwing code
function HLSubSurface(parent_surface, x,y,sx,sy )
local self = {}
-- fields
local srf = parent_surface:SubSurface( x,y, sx,sy )
-- methods
local meta = {
__index = function (t,k)
local tbl = getmetatable(srf)
return tbl[k]
end
}
setmetatable( self, meta )
return self
end
and my main code is :
sub = HLSubSurface( parent, 0,0, 160,320 )
x,y = sub.GetPosition()
but it's failing
./HDB/80_LeftBar.lua:19: bad argument #1 to 'SetFont' (SelSurface expected, got userdata)
It's because I need to provide srf as 1st argument to GetPosition() function ... but I strictly duno how to do that :(
I don't want to do it when calling GetPosition(),
x,y = sub.GetPosition()
but I'm looking for a way to do it transparently by setting it in meta's function.
In other words, I would like to have HLSubSurface object to inherit methods from SubSurface.
Any idea ?
Thanks.
Laurent
function HLSubSurface(parent_surface, x, y, sx, sy)
local srf = parent_surface:SubSurface(x, y, sx, sy)
local self = {
-- fields
....
}
setmetatable(self, {__index =
function (obj, key)
local parent_field
local parent_fields = getmetatable(srf).__index
if type(parent_fields) == "function" then
parent_field = parent_fields(key)
elseif parent_fields then
parent_field = parent_fields[key]
end
if type(parent_field) == "function" then
return
function(o, ...)
if o == obj then
return parent_field(srf, ...)
else
return parent_field(o, ...)
end
end
else
return parent_field
end
end
})
return self
end
And your main code would be:
sub = HLSubSurface( parent, 0,0, 160,320 )
x,y = sub:GetPosition()

Classes in Lua, how does it work

I'm new to Lua, and I'm trying to understand its OO part, for example :
lkw = {}
lkw.la= 0
function lkw:func(ge)
self.la = self.la + ge
end
function lkw:new()
local res = {}
setmetatable(res, self)
self.__index = self
return res
end
mylkw = lkw:new()
in this example the "class" lkw can create object using new, but what do self and index mean ?
should consider self as this in java/C++ and what is the index ?
This style of OOP is frequent in Lua. I do not like it because it is not explicit enough for me, but let me try to explain.
There are two confusing things: the use of the : sugar in function definitions and the use of the "class" as the metatable for its instances.
First, function a:b(...) is the same as a.b = function(self, ...), so let us remove all sugar:
lkw = {}
lkw.la = 0
lkw.func = function(self, ge)
self.la = self.la + ge
end
lkw.new = function(self)
local res = {}
setmetatable(res, self)
self.__index = self
return res
end
mylkw = lkw.new(lkw)
Now, this is "prototypal inheritance". lkw is the "prototype" for instances like mylkw. This is similar but slightly different from a "class".
When the new constructor is called, lkw is passed as the self argument.
The second and third lines of the constructor are weird. This is probably easier to understand:
lkw.new = function(self)
local res = {}
setmetatable(res, {__index = lkw})
return res
end
i.e.: if we do not find something in the instance we go look for it inside the prototype.
This explains how func works. The first time it is called, the instance will not contain a la key so lkw.la will be used.
The reason the code is not written this way is that the weird construction allows "prototypal inheritance": you could call "new" on mylkw and get an "instance of the instance" (i.e. in prototypal inheritance an instance and a child class are the same thing).
I think this is a very confusing feature. For reference this is about how I would write code that does about the same thing, with no inheritance:
local methods = {
func = function(self, ge)
self.la = self.la + ge
end
}
local lkw = {
new = function()
return setmetatable({la = 0}, {__index = methods})
end
}
local mylkw = lkw.new()

How do I make a Lua function return key,pairs to a yet unpopulated table?

I want the key pairs to be tableToPopulate.width = 30 and tableToPopulate.Height = 20
They are currently tableToPopulate[1] = 30 and tableToPopulate[2] = 20
local function X ()
code, code...
return 30,20
end
local tableToPopulate = {
x()
}
Why don't you just return a table?
local function X ()
return {width=30, height=20}
end
You could pass in the table you want the values set on, like this:
function x(tbl)
tbl.Height = 20;
tbl.Width = 30;
end
local t={}
x(t)
print(t.Height, t.Width)
although it may make more sense to use nested tables depending on how complex the structure will be of whatever is in the table.
function x(tbl)
table.insert(tbl, {Height = 20, Width = 30})
end
local t={}
x(t)
print(t[1].Height, t[1].Width)
which would be equivalent to this:
function x()
return {Height = 20, Width = 30}
end
local t = {x()}
print(t[1].Height, t[1].Width)
So really, it depends on how you want to group the data and which syntax you prefer.

nesting metatables in lua

In the code below it's my attempt to nest metatables on __index, but it's not working. What I want to do is if the value is t1 or t2 then return the associated value, otherwise call the function on the innermost __index. Is this possible?
so in the below x["hello"] can I return a value. I know I can just use a function on the outermost __index, but it seems I should be able to do this somehow using nested metatables.
tia.
x = { val = 3 } -- our object
mt = {
__index = {
t1 = 2,
t2 = 3,
__index = function (table, key)
print("here"..key)
return table.val
end
}
}
setmetatable(x, mt)
print(x["t1"]) -- prints 2
print(x.t2) -- prints 3
print(x["hello"]) -- prints nil???
This works but it seems like I could do it with metatables
x = { val = 3 } -- our object
mt1 = {
t1 = 2,
t2 = 3
}
mt = {
__index = function (table, key)
local a = mt1[key]
if a == nil then
print("here"..key)
a = "test"
end
return a
end
}
setmetatable(x, mt)
print(x["t1"])
print(x.t2)
print(x["hello"])
..and for anyone following along at home, here it is with nested metatables inline. Thanks for the tip Alexander that makes it a lot cleaner.
x = setmetatable(
{ val = 3 },
{
__index = setmetatable({
t1 = 2,
t2 = 3
},
{
__index = function (table, key)
print("here"..key)
return key
end
}
)
}
)
print(x["t1"])
print(x.t2)
print(x["hello"])
This works, but can I do it without declaring mt2?
x = { val = 3 } -- our object
mt2 = {
__index = function (table, key)
print("here"..key)
return key
end
}
mt = {
__index = {
t1 = 2,
t2 = 3
}
}
setmetatable(mt.__index, mt2)
setmetatable(x, mt)
print(x["t1"])
print(x.t2)
print(x["hello"])

Resources