1548 posts
Location
That dark shadow under your bed...
Posted 24 October 2012 - 09:43 AM
Hi all, I was just thinking that it would be great to be able to set your own metatables for your apis, when an api is loaded it is given a fixed, protected metatable that cannot be removed, I was wondering if there is no way we could specify our own metatables.
maybe the api could be its own metatable so if you make a function
function __call(self,...) --code-- end
in your api then it could be called as a function as well etc
we could also use a naming convention where if there is a file called
apiname_mt then then it would be used as the metatable
what do you think?
724 posts
Posted 24 October 2012 - 03:02 PM
Or check for names from short list including __call. If such function found in api, move it to api's metatable.
231 posts
Posted 24 October 2012 - 03:12 PM
You can almost do this by setting the metatable on getfenv() from the API, except for these lines in bios.lua, and setting the API to tAPI rather than tEnv
function os.loadApi( _sPath )
-- Code
local tAPI = {} -- These lines
for k,v in pairs( tEnv ) do
tAPI[k] = v
end
-- Code
end
What is the purpose of these lines anyway? As far as I can tell, APIs work fine with them removed from bios.lua, although there's possibly a good reason I haven't thought of yet.
1604 posts
Posted 24 October 2012 - 06:03 PM
You can already do this, since they don't have a metatable anymore (since version 1.4X, I don't remember which exactly). The only problem is that you can't do it from the api file, so you would need to make a program that loads the api and then sets it's metatable.
You can almost do this by setting the metatable on getfenv() from the API, except for these lines in bios.lua, and setting the API to tAPI rather than tEnv
function os.loadApi( _sPath )
-- Code
local tAPI = {} -- These lines
for k,v in pairs( tEnv ) do
tAPI[k] = v
end
-- Code
end
What is the purpose of these lines anyway? As far as I can tell, APIs work fine with them removed from bios.lua, although there's possibly a good reason I haven't thought of yet.
When the api is loaded, all it's functions are in that tEnv table, but it also has all the already loaded apis and global functions, because it's metatable is set to index the global environment. So, removing those lines would allow you to do something like:
os.loadAPI("someAPI")
someAPI.rednet.broadcast("Hello")
someAPI.term.clear()
someAPI.print("Hello World!")
And I don't think that's right ^_^/>/>
231 posts
Posted 24 October 2012 - 06:13 PM
Makes sense. Though you could add
local mt = getmetatable(tEnv)
if mt.__index == _G then -- Only if _G to allow API defined __index metamethod.
mt.__index = nil
end
1604 posts
Posted 24 October 2012 - 07:16 PM
Yes, but that would make the api unable to index the global environment, and wouldn't allow it to use any other api or global function. It is necesary to copy the functions to a new table to avoid theses isues, that's why it's done.
Here's an example of setting an api's metatable by loading it from a program:
mt = {} -- this is the metatable, put any metatags you want here
os.loadAPI("test") -- load the api normally
setmetatable(test, mt) -- set the metatable
Doing this from inside the api would be too hard, and I don't think it's worth it.
231 posts
Posted 24 October 2012 - 07:23 PM
True, I forgot about that. I guess it isn't really practical to use the environment directly. I see no reason you couldn't set the metatable of tAPI to the metatable of tEnv, excluding __index, though.
EDIT: Although since using getfenv to get the API to set the metatable on is somewhat a workaround anyway, It would probably be better just to have os.loadAPI load metatables by itself (for example if an API has a table named mt, or some other special name, it will be used as the metatable.)
724 posts
Posted 25 October 2012 - 03:22 PM
May be something like this?
function os.loadApi( _sPath )
-- Code
local tAPI = {} -- These lines
local mt={}
for k,v in pairs( tEnv ) do
if string.sub(k,1,2) == "__" then
mt[k]=v
else
tAPI[k] = v
end
setmetatable(tAPI,mt)
end
-- Code
end
So you can define function __index and it will be placed in metatable.