Control flow: Difference between revisions

Content deleted Content added
Early exit from loops: Rewrite lead, clarifying break and return.
Tags: harv or sfn error Mobile edit Mobile web edit Advanced mobile edit
Early exit from loops: Clean up lengthy Ada section and correct it (exit when is a conditional exit); split off subsection for multi-level breaks
Tags: Mobile edit Mobile web edit Advanced mobile edit
Line 387:
Other mechanisms for early exit include a <code>return</code> out of a subroutine executing the looped statements, breaking out of both the loop and the subroutine; and raising an exception. There are other [[#Proposed control structures|proposed control structures]], but they are not commonly implemented. This section treats early exit from only the loop ("break").
 
Most commonly, this is used by combining a conditional ('''if''' statement) with an unconditional break, as in Ada:
The following example is done in [[Ada (programming language)|Ada]] which supports both ''early exit from loops'' and ''[[#Loop with test in the middle|loops with test in the middle]]''. Both features are very similar and comparing both code snippets will show the difference: ''early exit'' must be combined with an '''if''' statement while a ''condition in the middle'' is a self-contained construct.
 
<syntaxhighlight lang="ada">
with Ada.Text IO;
with Ada.Integer Text IO;
 
procedure Print_Squares is
X : Integer;
begin
Read_Data : loop
Ada.Integer Text IO.Get(X);
exit Read_Data when X = 0;
Ada.Text IO.Put (X * X);
Ada.Text IO.New_Line;
end loop Read_Data;
end Print_Squares;
</syntaxhighlight>
 
 
In Ada, this is implemented with a standard infinite loop ('''loop''' - '''end loop''') that has an '''exit when''' clause in the middle (not to be confused with the '''exitwhen''' statement in {{slink||Proposed control structures}}):
 
<syntaxhighlight lang="ada">
loop
Get(X);
exit whenif X = 0; then
X : Integer exit;
end if;
-- Do something with X.
end loop;
</syntaxhighlight>
 
In Ada, this isform, implementedthe withcondition ais standardinterpreted infiniteas loop ('''loopuntil'''. -Some '''endlanguages, loop''')such thatas hasAda, have syntax for a conditional break, here an '''exit when''' clause in the middle (not to be confused with the '''exitwhen''' statement in {{slink||Proposed control structures}}); if available, this is more idiomatic:
Note that multiple '''exit when''' statements are possible. Ada also supports an unconditional '''exit''', so one can contrast the equivalent but unidiomatic '''if''' - '''exit''' form:
 
<syntaxhighlight lang="ada">
loop
Get(X);
ifexit when X = 0 then;
exit;
end if;
-- Do something with X.
end loop;
</syntaxhighlight>
 
This functions similarly to a [[#Loop with test in the middle|loop with test in the middle]], but in that case the test is part of the structure of the loop, dividing the body of the loop in half (visually indented at the same level as the start/end of loop), while early exit is unstructured: simply a statement that can appear anywhere in the body of the loop, and in fact multiple break statements are possible.
 
[[Python (programming language)|Python]] supports conditional execution of code depending on whether a loop was exited early (with a <code>break</code> statement) or not by using an else-clause with the loop. For example,
Line 441 ⟶ 424:
The <code>else</code> clause in the above example is linked to the <code>for</code> statement, and not the inner <code>if</code> statement. Both Python's <code>for</code> and <code>while</code> loops support such an else clause, which is executed only if early exit of the loop has not occurred.
 
==== Multi-level breaks ====
Some languages support breaking out of nested loops; in theory circles, these are called '''multi-level breaks'''. One common use example is searching a multi-dimensional table. This can be done either via multilevel breaks (break out of ''N'' levels), as in bash<ref>Advanced Bash Scripting Guide: [http://tldp.org/LDP/abs/html/loopcontrol.html 11.3. Loop Control]</ref> and PHP,<ref>PHP Manual: "[http://php.net/manual/en/control-structures.break.php break]"</ref> or via labeled breaks (break out and continue at given label), as in Go, Java and Perl.<ref>perldoc: [http://perldoc.perl.org/functions/last.html last]</ref> Alternatives to multilevel breaks include single breaks, together with a state variable which is tested to break out another level; exceptions, which are caught at the level being broken out to; placing the nested loops in a function and using return to effect termination of the entire nested loop; or using a label and a goto statement. C does not include a multilevel break, and the usual alternative is to use a goto to implement a labeled break.<ref>comp.lang.c FAQ list · "[http://c-faq.com/misc/multibreak.html Question 20.20b]"</ref> Python does not have a multilevel break or continue – this was proposed in [https://www.python.org/dev/peps/pep-3136/ PEP 3136], and rejected on the basis that the added complexity was not worth the rare legitimate use.<ref>[http://mail.python.org/pipermail/python-3000/2007-July/008663.html <nowiki>[</nowiki>Python-3000<nowiki>]</nowiki> Announcing PEP 3136], Guido van Rossum</ref>
 
The notion of multi-level breaks is of some interest in [[theoretical computer science]], because it gives rise to what is today called the ''Kosaraju hierarchy''.<ref name=kozen>{{cite book |first=Dexter |last=Kozen |date=2008 |chapter=The Böhm–Jacopini Theorem is False, Propositionally |title=Mathematics of Program Construction |series=Lecture Notes in Computer Science |doi=10.1007/978-3-540-70594-9_11 |volume=5133 |pages=177–192 |isbn=978-3-540-70593-2 |url=http://www.cs.cornell.edu/~kozen/papers/BohmJacopini.pdf |citeseerx=10.1.1.218.9241}}</ref> In 1973 [[S. Rao Kosaraju]] refined the [[structured program theorem]] by proving that it is possible to avoid adding additional variables in structured programming, as long as arbitrary-depth, multi-level breaks from loops are allowed.<ref>Kosaraju, S. Rao. "Analysis of structured programs," Proc. Fifth Annual ACM Syrup.