50 posts
Location
Germany
Posted 25 September 2012 - 07:33 PM
Hi,
I'm currently learning how to do object related stuff in Lua and wrote some functions for monitors. I'd like to make it such that I can access my functions the same way I access the standard functions of a monitor. For example:
function monitor.writePos(self, x, y, text)
self.setCursorPos(x, y)
local str = ""
while (#str ~= (width or #text)) do
str = str .. string.sub(text, 1, (width or #text))
end
self.write(str)
end
I'd like to somehow access this function using a "." instead of ":" and don't quite know how to do it. My current approach is creating a new table by merging the monitors peripheral table (the one obtained by using "wrap(side)" and my "monitor" table, but this way I have to use the ":".
Cyclonit
3790 posts
Location
Lincoln, Nebraska
Posted 25 September 2012 - 07:40 PM
Not sure if I understood the question properly, but are you looking to make an API of your own that you can call back to?
If so, you would need a separate file, and label it something like "myAPI". You would then add a function there, (not a local function, mind you) and do os.loadAPI("myAPI") at the start. Once that is complete, you can do myAPI.functionCall().
Still, if this is not what you needed, let us know. We'll try to help.
871 posts
Posted 25 September 2012 - 07:53 PM
if you need a self parameter in a native lua object method, you
must use ":", not "." The only workaround is to avoid needing the "self" parameter at all. When you wrap a peripheral, the wraper it returns most likely contains anonymous functions implemented on-the-fly that have the specified side hard-coded in, and so have no self parameter.
The peripheral.wrap function probably looks a lot like this:
function wrap(side)
local wrapper={}
for k,v in peripheral.getMethods(side) do
wrapper[k]=function(...) return peripheral.call(side,k,...) end
end
return wrapper
end
:edit: Not sure the above code actually works, with the side parameter being used inside the anonymous function?
50 posts
Location
Germany
Posted 25 September 2012 - 07:57 PM
Oh I know how to write create an API ^^
This is my current code:
http://pastebin.com/Q4MSiCYsWhenever I wrap a monitor using my own wrap function I can use my own two functions "writePos" and "writeAligned" by calling them using ":". However I would like to use the "." instead of ":" because all of the standard monitor functions are accessed like that too.
Edit:
One possible way to achieve this is by creating local proxy functions for every single object. A nicer approach would be cool.
871 posts
Posted 25 September 2012 - 08:00 PM
the standard ones either do not take a self parameter, or they are implemented in java.
if you need a self parameter in a native lua object method, you must use ":", not "."
50 posts
Location
Germany
Posted 25 September 2012 - 08:04 PM
Okay, thank you.
Is it possible to get the api's name from inside of the api then? As you can see in the code I posted earlier I am using a table called "monitor" to merge it with my object. Whenever I want to access the functions using the class instead of an object (like "cm.writePos()") I thus have to use "cm.monitor.writePos()". If there were a way to write "cf.tableMerge(obj, thisAPI)" instead of the current line 70 I could get rid of the monitor table.
3790 posts
Location
Lincoln, Nebraska
Posted 25 September 2012 - 08:07 PM
Wow, I was WAAAAY off. Disregard my previous post :P/>/>
50 posts
Location
Germany
Posted 25 September 2012 - 08:09 PM
Oh I already disregarded it :P/>/> Sorry for my bad English ^^'
445 posts
Posted 25 September 2012 - 08:41 PM
Actually you don't have to use ":" you could pass the param yourself
so if you usually call
monitor:writePos(10, 1, "blah")
you'd uuse
monitor.writePos(monitor,10,1,"blah")
50 posts
Location
Germany
Posted 25 September 2012 - 08:56 PM
Yes I know that, but I'd like to get the code a little shorter ^^.
1604 posts
Posted 25 September 2012 - 10:58 PM
If you want to use OOP then you'll need to use the : (or pass the table as argument like Pinkishu said).
You can do this without it though. It would be better to make the wrap function create a table that contains the functions you want using the wraped monitor, like peripheral.wrap does. Something like this:
function wrap(side)
local mon = peripheral.wrap(side)
if mon then
local t = {}
t.writePos = function(x, y, text)
mon.setCursorPos(x, y)
mon.write(text)
end
-- add more functions here
setmetatable(t, { __index = mon }) -- to make the monitor functions available
return t
end
end
871 posts
Posted 25 September 2012 - 11:21 PM
what MysticT said.
If you don't wanna put those whole functions in there as anonymous functions (writeAligned was pretty long), you can just do anonymous wrappers that provide the self parameter (this to be inserted in mysticT's after the t.writePos=.. line)
t.writeAligned=function(...) returm monitor.writeAligned(mon,...) end
1604 posts
Posted 25 September 2012 - 11:28 PM
what MysticT said.
If you don't wanna put those whole functions in there as anonymous functions (writeAligned was pretty long), you can just do anonymous wrappers that provide the self parameter (this to be inserted in mysticT's after the t.writePos=.. line)
t.writeAligned=function(...) returm monitor.writeAligned(mon,...) end
Yes, that would work the same, and also would let you call the functions without using the wraper, like:
local m = api.wrap("left")
m.writePos(1, 1, "Hello")
-- and
local mon = peripheral.wrap("left")
api.writePos(mon, 1, 1, "Hello")