Reputation:
I want to have an endless loop where the loop runs through nearly the entire program and at any point, based on a condition statement, I want it to exit that particular iteration of the loop and go back to the top and execute.
Is there a way this can be done?
It doesn't have to be an endless loop; it can be a for loop. I just want it to go to the next iteration of that loop.
Upvotes: 7
Views: 5564
Reputation: 5329
To answer your question, the easiest way (syntax-wise) I am aware of is to use another loop, nested in the first one. Exiting the inner loop imitates a continue statement.
loop
loop
...
exit when Some_Condition;
...
end loop;
end loop;
That said, If you need to do something like that, something smells bad. I woulkd personally use what ajb demonstrated in the begining of his answer, which is to use if statements. If the nesting level of the if statements gets too deep, you probably doing too much in the main and need to use functions/procedures anyway.
Upvotes: 3
Reputation: 31699
Ada doesn't have the equivalent of a continue
. The simplest way to accomplish the same thing is probably just to put the rest of the loop in an if
statement. So instead of something like this (here's an example where we're processing input lines and skipping those that begin with #):
while not End_Of_File (Input_File) loop
...
Read_A_Line (Input_File, Line);
if Line(Line'First) = "#" then
continue; -- ERROR--Ada doesn't have a continue statement
end if;
... process the input line
end loop;
you could say
while not End_Of_File (Input_File) loop
...
Read_A_Line (Input_File, Line);
if Line(Line'First) /= "#" then
... process the input line
end if;
end loop;
If it gets complicated, you may want to define a Boolean Need_To_Keep_Processing_Line
or something. If you have several points where you need the equivalent of continue
, you might end up with a multiply-nested if
; if this gets too ugly, then one thing I sometimes do is multiple non-nested if
's on the same Boolean:
if Need_To_Keep_Processing_Line then
...
if something then
if something-else then
Need_To_Keep_Processing_Line := false;
end if;
end if;
end if;
if Need_To_Keep_Processing_Line then -- again
...
end if;
Other alternatives have been mentioned: (1) goto
; (2) use a procedure and return
from various points; (3) exceptions. There are two problems with exceptions: first, this isn't really an exception, so you're using a construct for a purpose for which it wasn't intended, probably making your code less readable; and exceptions are inefficient (some compilers add extra code any time a block with an exception handler is entered; other compilers avoid this by setting up a table at compile time, but then a table search is required when an exception is raised). Using a procedure might be viable, depending on whether the loop body represents a concept that is easily named and identified. If it isn't, then extracting the loop body can hamper readability, because you're adding a procedure that doesn't really have a "procedure" purpose. The reason to avoid goto
is that back in the 70's we used to use it indiscriminately, leading to a lot of tangled code that went every which way. Despite what you may have heard about it, it doesn't have to make code unreadable if used in a disciplined fashion. I generally don't use it. But I also avoid continue
if programming in C-style languages, since to me it's just a glorified "goto" without the benefit of having a visible label at the end of your function to alert you to the fact that somebody is "going to" there.
But my real feeling about this is that if using if
leads to ugly code, your loop body is probably too big and needs to be broken down anyway. The solution wouldn't be to revert to one of the other solutions (exceptions or goto
), but rather to figure out the best way to make your loop body smaller and more readable.
Upvotes: 6
Reputation: 263497
Raise an exception that you handle in the body of the loop:
procedure Main is
Try_Again: exception;
begin
while Keep_Going loop
begin
-- lots of stuff
if Give_Up_On_This_Iteration then
raise Try_Again;
end if;
-- lots more stuff
exception
when Try_Again =>
null;
end;
end loop;
end Main;
Upvotes: 4