Lua tables, on function execute help
Dahknee 25 May 2016
Hey guys,
Environments are not my strong point, so I was wondering if I have a table like so:
So when I run: object:say("hey")
It could maybe (AN EXAMPLE) run the init function inside of the object? So say maybe when I run count
it will run object:init() then start count, with it all being internal, so all I have to do is call the function
and it is all done for me?
Thanks in advance,
Danny
Edited by DannySMc, 25 May 2016 - 01:03 PM.
Environments are not my strong point, so I was wondering if I have a table like so:
local object = { say = function( self, text ) print(text) return true end; count = function( self, limit ) for i=1, limit do print(i) end return true end; init = function( self ) -- This will do something end; }This is a basic example, but is there a way so every time a function is run in that table, I can run something just before it is called, example:
So when I run: object:say("hey")
It could maybe (AN EXAMPLE) run the init function inside of the object? So say maybe when I run count
it will run object:init() then start count, with it all being internal, so all I have to do is call the function
and it is all done for me?
Thanks in advance,
Danny
Edited by DannySMc, 25 May 2016 - 01:03 PM.
KingofGamesYami 25 May 2016
Hurray for metatables!
setmetatable( your_table, {__index = function( t, k ) if type( t[ k ] ) == "function" then doRandomStuff() end return rawget( t, k ) end}
Dahknee 25 May 2016
Thanks for the help, what is the raw get for? And will this go anywhere? So where would I get the return for that? In the running function?
Bomb Bloke 25 May 2016
The idea is that when you index into your table to get a function, the __index function will be called instead. That function then uses rawget() to retrieve the function you were trying to call in the first place.
The problem is that __index doesn't work that way... it's only used if the requested key doesn't exist in the table. Meaning that if you try to call a function that is in the table, none of Yami's code will actually do anything.
One way around this is to put the original functions in one table, then build the metatable out of a different one (which is kept entirely empty):
Now if you do object.say(), indexing into "object" to get "say" will call the __index function, which first calls "hiddenObject.init()" and then returns the "say" function from "hiddenObject" back to the original line - from where it'll be called, as you've got a () sitting directly after the index.
I've no idea if it'd execute faster or not, but another way to achieve much the same effect:
The problem is that __index doesn't work that way... it's only used if the requested key doesn't exist in the table. Meaning that if you try to call a function that is in the table, none of Yami's code will actually do anything.
One way around this is to put the original functions in one table, then build the metatable out of a different one (which is kept entirely empty):
local hiddenObject = {define bunch of functions here} local object = {} setmetatable( object , {__index = function( _, key ) if type( hiddenObject[ key ] ) == "function" and key ~= "init" then hiddenObject.init() end return hiddenObject[ key ] end}
Now if you do object.say(), indexing into "object" to get "say" will call the __index function, which first calls "hiddenObject.init()" and then returns the "say" function from "hiddenObject" back to the original line - from where it'll be called, as you've got a () sitting directly after the index.
I've no idea if it'd execute faster or not, but another way to achieve much the same effect:
local hiddenObject = {define bunch of functions here} local object = {init = hiddenObject.init} for key, value in pairs(hiddenObject) do if type(value) == "function" and key ~= "init" then object[key] = function(...) object.init() return value(...) end end end
KingofGamesYami 25 May 2016
Dahknee 25 May 2016
KingofGamesYami, on 25 May 2016 - 04:35 PM, said:
Ahh, er hm
Bomb Bloke, on 25 May 2016 - 03:45 PM, said:
The idea is that when you index into your table to get a function, the __index function will be called instead. That function then uses rawget() to retrieve the function you were trying to call in the first place.
The problem is that __index doesn't work that way... it's only used if the requested key doesn't exist in the table. Meaning that if you try to call a function that is in the table, none of Yami's code will actually do anything.
One way around this is to put the original functions in one table, then build the metatable out of a different one (which is kept entirely empty):
I've no idea if it'd execute faster or not, but another way to achieve much the same effect:
The problem is that __index doesn't work that way... it's only used if the requested key doesn't exist in the table. Meaning that if you try to call a function that is in the table, none of Yami's code will actually do anything.
One way around this is to put the original functions in one table, then build the metatable out of a different one (which is kept entirely empty):
local hiddenObject = {define bunch of functions here} local object = {} setmetatable( object , {__index = function( _, key ) if type( hiddenObject[ key ] ) == "function" and key ~= "init" then hiddenObject.init() end return hiddenObject[ key ] end}Now if you do object.say(), indexing into "object" to get "say" will call the __index function, which first calls "hiddenObject.init()" and then returns the "say" function from "hiddenObject" back to the original line - from where it'll be called, as you've got a () sitting directly after the index.
I've no idea if it'd execute faster or not, but another way to achieve much the same effect:
local hiddenObject = {define bunch of functions here} local object = {init = hiddenObject.init} for key, value in pairs(hiddenObject) do if type(value) == "function" and key ~= "init" then object[key] = function(...) object.init() return value(...) end end end
Hmm interesting, but it seems to be a lot more code than I was hoping for... :/