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

Background Message Receiving

Started by ProjectXMark1, 11 November 2012 - 05:18 AM
ProjectXMark1 #1
Posted 11 November 2012 - 06:18 AM
I'm trying to make a rednet messaging program that can receive messages at all times; can someone show me how to write a function that operates in the background?
Espen #2
Posted 11 November 2012 - 07:42 AM
Here's an example for how to use the parallel API.
This program will listen for events while you are "stuck" in the read() of inputFunc():
Spoiler
-- Just a little helper function.
local function clear()
	term.setCursorPos(1,1)
	term.clear()
end

local function inputFunc()
	while true do
		term.clear()
		term.setCursorPos(1, 19)
		write( "Type "exit" or press END to exit." )
		term.setCursorPos(10, 7)
		write( "Input: " )

		local input = read()
		if string.lower( input ) == "exit" then
			clear()
			return   -- and thus yielding this coroutine.
		end
	end
end

local function eventListener()
	while true do
		local sEvent, sParam = os.pullEvent()

		if sEvent == "key" then
			if sParam == keys.space then
				local oldX, oldY = term.getCursorPos()
				term.setCursorPos(1, 1)
				write( "Marking spaces..." )
				term.setCursorPos(oldX, oldY + 1)
				write("^")

			elseif sParam == keys["end"] then
				clear()
				return   -- and thus yielding this coroutine.
			end
		end

		if sEvent == "char" then
			-- do something
		end

		if sEvent == "redstone" then
			-- do something
		end
	end
end

-- Start coroutines.
parallel.waitForAny( inputFunc, eventListener )


What inputFunc() does:
  • Returns from the function if "exit" is entered.
What eventListener() does:
  • Marks the location of an entered space, whenever the space key is pressed.
  • Returns from the function if the END key is pressed.
The important parts to keep in mind are:
parallel.waitForAny basically means: "Wait for any of these functions to yield/return"
parallel.waitForAll basically means: "Wait for all of these functions to yield/return"

If, for example, you'd change the code above to use waitForAll, then after entering "exit" the program will still be running eventListener().
That is because waitForAll is still waiting for it to yield/return.
So you still have to press END to completely exit out of the program.
And vice versa, i.e. if you first press END, then you'd still have to enter "exit" to end the program completely.

Another thing to keep in mind is that you only pass the function names without brackets!
Otherwise the functions would first be run and their return value be passed to parallel.waitForAny().
But we want to pass the references to the functions, not their return values! Like so:
parallel.waitForAny( inputFunc, eventListener )
zekesonxx #3
Posted 11 November 2012 - 08:17 PM
Espen you just fixed my entire program. Thanks!
ProjectXMark1 #4
Posted 18 November 2012 - 06:53 AM
Is the "–Start coroutines" bit just calling the two functions? Can I run a function inside the function or call the function again without yielding the parent function?

Just checking.
Espen #5
Posted 18 November 2012 - 07:56 AM
Is the "–Start coroutines" bit just calling the two functions? Can I run a function inside the function or call the function again without yielding the parent function?

Just checking.
Yes you can run functions within functions. And yes, you can also let the function recursively call itself without yielding it.
For example, if you'd call inputFunc() from within itself, then when you return from it the first time, you'll land back in the inputFunc() at the point where it called itself. And only if THAT returns now, does it yield.
Every recursive call is nested deeper and deeper. It's like a Matryoshka doll, i.e. everytime you let inputFunc() recursively call itself, you open the next layer of the doll, and on and on.
Now if you want to come back to the outermost layer, you first have to close the last one opened (return), then the second-last, etc. … until you're at the first layer.
If you return from that as well, then you're finally yielding.

Hope this wasn't more complicated that I set it out to be. I'm not feeling the explain-flow today. :)/>/>