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

[Lua][Question] Is there a simple way to break out of multiple functions?

Started by Fizzgig, 28 December 2012 - 07:17 AM
Fizzgig #1
Posted 28 December 2012 - 08:17 AM
I have written a very elaborate turtle treefarm with over 1000 lines of code. I am very close to calling it DONE! But there is still one feature I would like to add.

Last week I asked for help about adding a user controlled "break" from the main sleep function. It says "Press X to cancel." and the solution provided works beautifully. Now I would like to improve the rest of this thing so that the user can cancel out of any action. Upon doing so, the turtle would return from where ever it is and then end the program (er… actually I also have a menu UI system. If possible Id like it to drop to the menu…) The problem is that some of the turtle actions are buried 4 and 5 functions deep. A simple "Press x to cancel." would have to break out of multiple functions.

I can provide some portions of the code below to give an idea of what I mean, but this is just an example. It is not perfect since it is snippets only an it would require the full code to work properly, if at all. I wont post everything here because of its length… but I will probobly provide the finished program for the community when it is done.



--Functions

function forward(num)
while num > 0 do
  CheckFuel()
  if turtle.forward() then
   CollectItems() --a function to call turtle.suck()
   xpos=xpos+1
   num = num-1
   CountItems() --a function to find out if the turtle has full inv
  else
   turtle.dig()
  end
end
end

function go(x,y)
setdir(2)   --a function to rotate the turtle
forward(x-xpos)
end

function scanforitems(num)
term.clear()
term.setCursorPos(1,1)
print("Status - Looking for Items... ")

   --print("Press 'x' to cancel.")  --This is the part I want to add
scan = true
go((spacing*num),ypos)
scan = false
end

function sleepmode(num)
timer = os.startTimer(1)
repeat
  term.clear()
  term.setCursorPos(1,1)
  print("Status - Sleeping... "..num.."sec")
  print("Press 'x' to cancel.")
  
  local id, p1 = os.pullEvent()
  if id == "key" and p1 == 45 then return false
  elseif id == "timer" and p1 == timer then
   num = num-1
   timer = os.startTimer(1)
  end
until num < 0
end


--Main Code
while true do
for i = 1,ycount do
  scanforitems(i)
end
home()   --this function returns the turtle to his home chest
organize()  --this function matches inv items to the "safe items" and discards the rest
if sleepmode(duration) == false then
  term.clear()
  term.setCursorPos(1,1)
  break
end
end
(pasting the code in the editor messed up some of the tabs) :unsure:/>

Please notice the sleepmode function above. It is posted in its entirety. That is an exaple of how I "think" I want the rest of the user cancelations to work. (if possible?)

Another thing to note, I do not wish to use rednet for this. I feel that the addition of rednet commands could potentially double the size of this code and introduce many more complications. Im looking for a simple and elegant way to do this. Maybe I will play with rednet in a different project. :P/>

Thanks for any help and advice. And sorry for the lengthyness… (it was hard to decide which portions to include. "too little"? "too much"?)
kornichen #2
Posted 28 December 2012 - 08:22 AM
Yes! I did it like this:


while true do
    while true do
	    [...]
	    a = 1
	    break
    end
    if a == 1 then break end
end
Lyqyd #3
Posted 28 December 2012 - 08:58 AM
With functions, you can use a return code. When you receive the user input command to stop, return a code of some sort (number, string, whatever) and have the code that called the function check the return value and act appropriately.
GravityScore #4
Posted 28 December 2012 - 09:02 AM
Yes! I did it like this:


while true do
	while true do
		[...]
		a = 1
		break
	end
	if a == 1 then break end
end

Just a suggestion:
To break out of multiple while loops like that, you could just return out of the function - that is, unless you want to get to a specific point in the function.

For example:

function test1()
  while true do
	while true do
	  -- Do stuff. Just an example below:
	  local option = promptTheUserForAnOption()
	  if option == "exit" then
		return
	  end
	end
  end
end

while true do
  test1()
end

Or like the code you posted:

while true do
  while true do
	[...]
	return
  end
end
Fizzgig #5
Posted 28 December 2012 - 09:16 AM
Lyqyd - Yes I already use many return values for my functions. The above posting is very incomplete. That would mean I would have to write alot of return checks to include a different value and pass the value on to the original function, and on and on. Im starting to think this is too dificult now xD. Maybe i should just set it up better next time LOL
Fizzgig #6
Posted 28 December 2012 - 09:38 AM
Im startin to get Ideas maybe. Sorta like the return but instead of following down the chain with a cancel value it could be like an AllStop boolean. Then every function could react if it was set true. I wouldnt have to fiddle with the web of return values.

I feel this is a needed feature for the turtle because unlike a stationary computer the turtle holds your things. Like a full stack of fuel you probobly just gave it. If I just left this to Ctrl+T terminate then its stuck there and the only solution is to smash it with a pick. I find that unacceptable.

I have to make a safe return so that it can be prepared for a reset.

Anyway - :P/> Back at it!
ChunLing #7
Posted 28 December 2012 - 12:00 PM
This problem pretty much goes away if you take care to make your basic functions "instant return" as much as possible.

If you totally need to have a termination to break out of multiple layers of functions, then you can always just call a nil value. A complete hack, but effective.
Fizzgig #8
Posted 28 December 2012 - 01:22 PM
I guess for "instant return" I may not understand… do you mean something like this?

rather than calling:
if functionName() then… –it is expecting only one type of thing

I should call:
Var = FunctionName()
If Var == (something) then return Var
elseif etc…

If I got it wrong could you describe it?
remiX #9
Posted 28 December 2012 - 09:23 PM
Just use return where you want it to stop…
Fizzgig #10
Posted 29 December 2012 - 03:52 AM
Well I'm forcing this to work, its a little more messy than I prefer. Added about 100 extra lines and counting… alot of my newer functions seem to have broke out on their own tho. But the functions I wrote at the begining of this project need alittle extra coercion (bunch of "if not allstop then" everywhere) yuck.

I definently gotta plan it out better for my next project.
ChunLing #11
Posted 29 December 2012 - 05:20 PM
I just mean that you should write your basic functions to return as fast as possible. Then organize your functions so that generally higher level functions call lower level functions.
Exerro #12
Posted 29 December 2012 - 09:35 PM
You can use error(string) to kind of crash the program and that will always exit