• This is a read only backup of the old Emudevs forum. If you want to have anything removed, please message me on Discord: KittyKaev

[Lua] 'goto' statement.

Grandelf

Esteemed Member
Hello there,

I am making this topic because since Lua 5.2 we have acces to this amazing thing called a 'goto' statement,
which is absolutely awesome in my opinion. I haven’t seen anyone using it yet, which can either be that most of the people here
doesn’t exactly know how it works or haven’t heard of it yet, or it can simply be that no one has found any use for it.
Either way I felt like making a small tutorial for it.

What is a goto statement exactly?

A goto statement is much like a 'return' or 'break' statement, it basically stops some code from running.
However a goto statement skips code rather than completely stopping all the code in a loop (break) or function (return).
To skip code and 'goto' a certain point in your code however, you need something so the goto statement knows where to go to.
This is called a label.

A goto statement jumps the execution of a program to a corresponding label.
How do I use a goto statement?

Knowing all this, it is clear that goto needs some kind of variable passed into it, and a label has to be made somehow,
somewhere in the code. As an example I decided to use the 'continue' statement from languages like C++ or Java.
Before the goto statement was introduced there was no way to replicate this behavior in Lua.
For those of you who don’t know what a continue statement does, it basically skips to the next iteration inside a loop.

The continue statement passes control to the next iteration of the nearest enclosing do, for, or while statement in which it appears, bypassing any remaining statements in the do, for, or while statement body.
To illustrate this I have written a small code, that will show you the use of continue.
Code:
int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for (int i = 0; i < arr.length; i++) do {
	/* If the index = 3 then we skip this iteration and go to the next iteration
	which has an index of 4. */ 
	if (i == 3)
		continue; 
	
	arr[i] = arr[i]*2;
}
The array will now contain the following: {2, 4, 3, 8, 10, 12, 14, 16, 18, 20}. As you can see it multiplied every number by 2,
except for the third element, because a continue statement was called and it skipped the rest of the code.

The continue statement in Lua.

Now lets implement this behavior in Lua, using a goto statement. Like I said before,
a goto statement requires a label which will be the argument for goto. Now how do you make this label?
That may be more easy than you would’ve expected. To make a label you simply use 2 colons, followed by the label name followed by two more colons.
After making the label you will have to place it inside your code, keep in mind that wherever you put this label,
that is where the goto statement will jump to as seen later in the continue example which we will be making.

Now we know what a goto statement is, and how we make a label it is time use the goto statement. To start making our continue statement,
we’re going to need a label name. Because we’re making a continue statement, I am going to call this label continue.
Code:
::continue::
The code we’re going to use will be the same as the previous example, but in Lua.
Code:
local arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for i=1, #arr do
	if (i == 3) then
	        -- The continue statement, which we do not have yet.
        end

        arr[i] = arr[i] *2;
end
Now to implement a continue statement, we will have to add the continue label in the code on a place where we want the code to jump to.
Seeing as we want to skip that iteration and go to the next one, we can simply place the label after ‘arr = arr *2;’.
Then it will skip to the end of the iteration and continue the next iteration. After that, all that is left to do is call the ‘goto labelname’ and we’re done.
Code:
local arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for i=1, #arr do
	if (i == 3) then
	        goto continue;
        end

        arr[i] = arr[i] *2;
        ::continue::
end

The goto statement outside a loop.

Do note that unlike a continue statement, a goto statement does not have to be called inside a loop. Another simple example to illustrate a goto statement outside a loop would be:
Code:
local a = 0;
local b = 0;

-- 50% chance of going to codeA otherwise codeB.
if math.random(2) == 1 then
	goto codeA;
else
	goto codeB;
end

::codeA:: do
	a = a + 10; return print(a, b);
end
::codeB:: do 
	b = b + 10; return print(a, b);
end
In this code, we simply start off by deciding what code to run, it has a 50% chance to run codeA, otherwise it will run codeB.
Therefor there are two possible outcomes, that it will print to the console. This will either be, ’10, 0’ or ’0, 10’ depending on whether it ran codeB or codeC.
Note: The return statement will actually do the job of stopping the code from running both codeA aswell as codeB.

For those of you, who would like to see more examples of how this works, you can check out this link: http://lua-users.org/wiki/GotoStatement.

I hope this was useful to some people, in my opinion this is a really powerful tool that can be useful in a lot of situations.

Grandelf.

Edit: There seems to be some kind of debate going on whether to use this or not, so I am simply going to say this:
Everyone should decide for themselves if they want to use this or not, knowing about goto on the other hand
isn't going to harm you, and that's exactly the point of this tutorial.

In this tutorial I gave two examples, the first one using continue, is something I would use and is actually really helpful in my opinion.
The second example in this tutorial is purely there to illustrate a goto statement outside of a loop.

To illustrate the use of goto a bit more I have written a small script that will generate a code under two conditions.
In this script I used two labels 'continue' and 'redo', note that I could've used only continue however this way
you're basically making sure something is how you want it to be, before processing it. Also will it illustrate that you can
jump backwards aswell instead of just forward like in the previous examples.
Code:
-- A simple script that will generate a code under two conditions, 
-- you can't have 2 of the same digits in a row and we are only
-- using even numbers.
local codeLength = 10;
local function generateCode()
	local str = "";
	while #str ~= codeLength do
		::redo::
		local number = math.random(9);
		-- The number must be different from the last one before 
		-- it will be taken into consideration.
		if number == tonumber(str:sub(#str, #str)) then 
			goto redo; -- Obviously we could've used continue here aswell.
		elseif number %2 ~= 0 then -- Number is different so we consider using it.
			goto continue; -- Number declined.
		end
		str = str .. number;
		::continue::
	end
	return str;
end
print(generateCode());
 
Last edited:

Rochet2

Moderator / Eluna Dev
Additional reason: Backwards compatibility

Quick note; codeC gets executed when codeB is executed
This way C is always 10 and A is always 10, but B keeps changing
The example is so annoyingly put to farm mislogic even if explained xd, the comments are "wrong"

Example:

Code:
goto U
print("_Y")::Y::print("Y_")
print("_U")::U::print("U_")
print("_I")::I::print("I_")

All 3 prints after the label U get printed, so U_ _I I_
 
Last edited:

Grandelf

Esteemed Member
Oops, you're right. Yea I really made that just on top of my head, maybe I should've tested it.. oh well.

Edit: That actually made me realise how stupid that code was, I actually misinterpreted something which I didn't know until now,
so thanks for that, I guess =P.
 
Last edited:

Kaev

Super Moderator
Never, never, never, NEVER use Goto. Never.
There is a reason, why you never see it.
 

Kaev

Super Moderator
Google it. It's a veeery bad practice. And a good code NEVER needs GoTo.
Pic related.
goto.png
 

Grandelf

Esteemed Member
Google on the other hand, isn't always right =P. I must disagree with this, I find goto very useful in situations where I want
to have some sort of continue or redo construction. True enough there are situations in which I wouldn't use it, the second
example I gave is not how I would do such a thing, but it does illustrate the use of goto.

I guess this quote from 'Programming in Lua' would describe pefectly of what is going on here =P
There has been a long going debate about goto, with some people arguing
even today that they are harmful to programming and should be banned from
programming languages. Nonetheless, several current languages offer goto,
with good reason. They are a powerful mechanism and, when used with care,
can only improve the quality of your code.
 
Last edited:

Kaev

Super Moderator
It can't improve the quality of your code. It will make it hard to debug and hard to read, also called bad code.
And if you want to loop something, use a loop, not goto.
 

Grandelf

Esteemed Member
This is all a matter of opinion and I think people should decide for themselves if they want to use this or not.

And if you want to loop something, use a loop, not goto.
I am not trying to loop through anything, what I am doing is simulating a continue statement,
which without goto is not possible in Lua. Which is exactly why I think goto is a useful
addition to Lua.
 

Rochet2

Moderator / Eluna Dev
It can't improve the quality of your code. It will make it hard to debug and hard to read, also called bad code.
And if you want to loop something, use a loop, not goto.

You can misuse a lot of things, but that doesnt mean you should completely ignore them. There are cases where they are more benefit than bad.
I wanted to give some quote, so here is one:
http://stackoverflow.com/questions/...tiple-nested-for-loops#comment1084808_1257760
Don't be afraid to use a goto if that is the best option

Most of the uses I read I like continue and nested break which tend to be an issue all the time for me personally.
 
Top