This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Cyclonit's profile picture

Use "." instead of ":"

Started by Cyclonit, 25 September 2012 - 05:33 PM
Cyclonit #1
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
Cranium #2
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.
GopherAtl #3
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?
Cyclonit #4
Posted 25 September 2012 - 07:57 PM
Oh I know how to write create an API ^^

This is my current code:
http://pastebin.com/Q4MSiCYs

Whenever 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.
GopherAtl #5
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 "."
Cyclonit #6
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.
Cranium #7
Posted 25 September 2012 - 08:07 PM
Wow, I was WAAAAY off. Disregard my previous post :P/>/>
Cyclonit #8
Posted 25 September 2012 - 08:09 PM
Oh I already disregarded it :P/>/> Sorry for my bad English ^^'
Pinkishu #9
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")
Cyclonit #10
Posted 25 September 2012 - 08:56 PM
Yes I know that, but I'd like to get the code a little shorter ^^.
MysticT #11
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
GopherAtl #12
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
MysticT #13
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")