Control flow: Difference between revisions

Content deleted Content added
See also While loop.
 
(972 intermediate revisions by more than 100 users not shown)
Line 1:
{{Short description|Execution order of computer commands}}
In [[computer science]] and in [[programming]],
{{Distinguish|Flow control (data)}}
statements in pseudo-code or in a program
{{Loop constructs}}<!-- DO NOT remove. Discuss navigation concept at [[Talk:Do while loop#Helpbox experiment]] -->
are normally obeyed one after the other in the order in which they are written
In [[computer science]], '''control flow''' (or '''flow of control''') is the order in which individual [[Statement (computer science)|statements]], [[Instruction (computer science)|instructions]] or [[function call]]s of an [[imperative programming|imperative]] [[computer program|program]] are [[Execution (computing)|executed]] or evaluated. The emphasis on explicit control flow distinguishes an ''[[imperative programming]]'' language from a ''[[declarative programming]]'' language.
(sequential flow of control).
Most programming languages have '''control flow''' statements which allow
variations in this sequential order:
* statements may only be obeyed under certain conditions (choice),
* statements may be obeyed repeatedly (loops),
* a group of remote statements may be obeyed (subroutines).
 
Within an imperative [[programming language]], a ''control flow statement'' is a statement that results in a choice being made as to which of two or more paths to follow. For [[Strict programming language|non-strict]] functional languages, functions and [[language construct]]s exist to achieve the same result, but they are usually not termed control flow statements.
The use of subroutines does not normally cause any control flow problems,
but see the discussions below on early return, error recovery, and labels as parameters.
 
A set of statements is in turn generally structured as a [[Block (programming)|block]], which in addition to grouping, also defines a [[lexical scope]].
At the machine/assembly language level,
it is usually the case that
the only instructions available for handling choice and/or loops
are ''goto'' and ''conditional goto''
(often known as variations of ''jump'' and/or ''branch'').
[[Compiler]]s for high-level [[programming language]]s must translate
all control-flow statements into these primitives.
 
[[Interrupt]]s and [[Signal (computing)|signals]] are low-level mechanisms that can alter the flow of control in a way similar to a [[subroutine]], but usually occur as a response to some external stimulus or event (that can occur [[Asynchronous systems|asynchronously]]), rather than execution of an ''in-line'' control flow statement.
Help! I know that a reference to [[Sequence points]] belongs around here somewhere but this is the first wikipedia page I've edited. I know someone will do the right thing with this.
 
At the level of [[machine language]] or [[assembly language]], control flow instructions usually work by altering the [[program counter]]. For some [[central processing unit]]s (CPUs), the only control flow instructions available are conditional or unconditional [[Branch (computer science)|branch]] instructions, also termed jumps. However there is also [[Predication_(computer_architecture)|predication]] which conditionally enables or disables instructions ''without'' branching: as an alternative technique it can have both [[Predication_(computer_architecture)#Advantages|advantages]] and disadvantages over branching.
= Primitives =
== Labels ==
 
== Categories ==
In a few programming languages (e.g. [[Fortran]], [[BASIC programming language|BASIC]]),
[[File:Maldi informatics figure 7.JPG|thumb|upright=1.3|A [[state diagram]] of a peptide ion mass mapping search process]]
a label is just a whole number which appears at the beginning of a statement, e.g.
The kinds of control flow statements supported by different languages vary, but can be categorized by their effect:
1234 X = 3
* Continuation at a different statement (unconditional [[Branch (computer science)|branch]] or jump)
* Executing a set of statements only if some condition is met (choice - i.e., [[conditional branch]])
* Executing a set of statements zero or more times, until some condition is met (i.e., loop - the same as [[conditional branch]])
* Executing a set of distant statements, after which the flow of control usually returns ([[subroutine]]s, [[coroutine]]s, and [[continuation]]s)
* Stopping the program, preventing any further execution (unconditional halt)
 
== Primitives ==
In many programming languages, a label is an [[identifier]],
=== Labels ===
which is attached to a statement by using a colon ':', e.g.
{{main article|Label (computer science)}}
Success:print("target has been found")
A [[Label (programming language)|label]] is an explicit name or number assigned to a fixed position within the [[source code]], and which may be referenced by control flow statements appearing elsewhere in the source code. A label marks a position within source code and has no other effect.
 
[[Line number]]s are an alternative to a named label used in some languages (such as [[BASIC]]). They are [[Natural number|whole numbers]] placed at the start of each line of text in the source code. Languages which use these often impose the constraint that the line numbers must increase in value in each following line, but may not require that they be consecutive. For example, in BASIC:
Historical note: [[Algol 60]] allowed both whole numbers and identifiers as labels
(both attached by colons to statements),
but few if any implementations allowed whole numbers.
== Goto ==
 
<syntaxhighlight lang="qbasic">
The most common form for the unconditional transfer of control is just
10 LET X = 3
'''goto''' label
20 PRINT X
Conditional transfer of control varies from language to language, e.g.
</syntaxhighlight>
IF test THEN label
IF (test) GOTO label
'''if''' test '''then''' '''goto''' label;
'''if''' (test) '''goto''' label;
 
In other languages such as [[C (programming language)|C]] and [[Ada (programming language)|Ada]], a label is an [[identifier]], usually appearing at the start of a line and immediately followed by a colon. For example, in C:
For a fuller discussion on the drawbacks of '''goto''', see [[Goto]].
In brief, undisciplined use of '''goto''' leads
to [[spaghetti code]] which tends to be unmaintainable;
see [[Edsger Dijkstra]]'s comments in
[http://www.acm.org/classics/oct95/ Go to statement considered harmful].
However, [[Donald Knuth]] has shown in
[http://pplab.snu.ac.kr/courses/PL2001/papers/p261-knuth.pdf Structured Programming with goto statements]
that disciplined use of '''goto''' may be necessary
to emulate missing control-flow structures.
 
<syntaxhighlight lang="c">
A number of authors have pointed out that using '''goto''' is often acceptable,
Success: printf("The operation was successful.\n");
provided that control is transferred to some later statement (forward jump)
</syntaxhighlight>
and that control is not transferred into the middle of some other structured statement.
Some of the control-flow statements available in high-level programming languages
are effectively disguised '''goto'''s which comply with these conditions,
e.g. '''break''', '''continue''', '''return''' as found in C/C++.
 
The language [[ALGOL 60]] allowed both whole numbers and identifiers as labels (both linked by colons to the following statement), but few if any other [[ALGOL]] variants allowed whole numbers. Early [[Fortran]] compilers only allowed whole numbers as labels. Beginning with Fortran-90, alphanumeric labels have also been allowed.
== Subroutines ==
 
=== Goto ===
The terminology for [[subroutine]]s varies;
{{main article|GOTO}}
they may alternatively be known as routines, procedures, or sometimes methods.
The ''goto'' statement (a combination of the English words ''[[wiktionary:go|go]]'' and ''[[wiktionary:to|to]]'', and pronounced accordingly) is the most basic form of unconditional transfer of control.
If they can be used in an expression and return a single result,
they may also be known as functions.
 
Although the [[Keyword (computing)|keyword]] may either be in upper or lower case depending on the language, it is usually written as:
In the 1950's, computer memories were very small by current standards
'''goto''' ''label''
so subroutines were used primarily to reduce program size;
The effect of a goto statement is to cause the next statement to be executed to be the statement appearing at (or immediately after) the indicated label.
a piece of code was written once and then used many times
from various other places in the program.
Nowadays, subroutines are more fequently used to help make a program more structured,
e.g. by isolating some particular algorithm or hiding some particular data access method.
If many programmers are working on a single program,
subroutines can be used to help split up the work.
 
Goto statements have been [[considered harmful]] by many computer scientists, notably [[Edsger W. Dijkstra|Dijkstra]].
Subroutines can be made much more useful by providing them with parameters,
e.g. many programming langauges have a built-in square root subroutine
whose parameter is the number you wish to find the square root of.
 
=== Subroutines ===
Some programming languages allow [[recursion]],
{{main article|Subroutine}}
i.e. subroutines can call themselves directly or indirectly.
The terminology for [[subroutine]]s varies; they may alternatively be known as routines, procedures, functions (especially if they return results) or methods (especially if they belong to [[Class (programming)|classes]] or [[type class]]es).
Certain algorithms such as [[Quicksort]] and various tree-traversals are
very much easier to express in recursive form than in non-recursive form.
 
In the 1950s, computer memories were very small by current standards so subroutines were used mainly to reduce program size. A piece of code was written once and then used many times from various other places in a program.
The use of subroutines does slow a program down slightly,
due to the overhead of passing parameters, calling the subroutine,
entering the subroutine (may involve saving information on a stack), and returning.
The actual overhead depends on both the hardware instructions available
and on any software conventions which are used;
excluding parameters, the overhead may range from 2 to 14 instructions, or worse.
Some compilers may effectively insert the code of a subroutine
[[In-line expansion|inline]] at the point of call
to remove this overhead.
 
Today, subroutines are more often used to help make a program more structured, e.g., by isolating some algorithm or hiding some data access method. If many programmers are working on one program, subroutines are one kind of [[Modularity (programming)|modularity]] that can help divide the work.
In some programming languages, the only way of returning from a subroutine is
by reaching the physical end of the subroutine.
Other languages have a '''return''' statement.
This is equivalent to a forward jump to the physical end of the subroutine
and so does not complicate the control flow situation.
There may be several such statements within a subroutine if required.
 
=== Sequence ===
In most cases, a call to a subroutine is only a temporary diversion
{{main article|Structured programming}}
to the sequential flow of control, and so causes no problems for control flow analysis.
A few languages allow labels to be passed as parameters,
in which case understanding the control flow becomes very much more complicated,
since you may then need to understand the subroutine to figure out what might happen.
 
In structured programming, the ordered sequencing of successive commands is considered one of the basic control structures, which is used as a building block for programs alongside iteration, recursion and choice.
 
== Minimal structured control flow ==
{{See also|Structured program theorem}}
In May 1966, Böhm and Jacopini published an article<ref>Böhm, Jacopini. "Flow diagrams, turing machines and languages with only two formation rules" [[Comm. ACM]], 9(5):366-371, May 1966.</ref> in ''Communications of the ACM'' which showed that any program with '''goto'''s could be transformed into a goto-free form involving only choice (IF THEN ELSE) and loops (WHILE condition DO xxx), possibly with duplicated code and/or the addition of Boolean variables (true/false flags). Later authors showed that choice can be replaced by loops (and yet more Boolean variables).
 
That such minimalism is possible does not mean that it is necessarily desirable; computers theoretically need only [[One instruction set computer|one machine instruction]] (subtract one number from another and branch if the result is negative), but practical computers have dozens or even hundreds of machine instructions.
In May 1966, BÖhm and Jacopini published an article in Communications of the ACM
which showed that any program with '''goto'''s could be transformed into a goto-free form
involving only choice (IF THEN ELSE) and loops (WHILE condition DO xxx),
possibly with duplicated code and/or the addition of Boolean variables (true/false flags).
''Can someone check for a possible 1964 publication of this in Italian?''
Later authors have shown that choice can be replaced by loops (and yet more Boolean variables).
 
Other research showed that control structures with one entry and one exit were much easier to understand than any other form,{{citation needed|date=July 2014}} mainly because they could be used anywhere as a statement without disrupting the control flow. In other words, they were ''composable''. (Later developments, such as [[non-strict programming language]]s – and more recently, composable [[software transactional memory|software transactions]] – have continued this strategy, making components of programs even more freely composable.)
The fact that such minimalism is possible does not necessarily mean that it is desirable;
after all, computers theoretically only need one machine instruction
(subtract one number from another and branch if the result is negative),
but practical computers have dozens or even hundreds of machine instructions.
 
Some academics took a purist approach to the Böhm–Jacopini result and argued that even instructions like <code>break</code> and <code>return</code> from the middle of loops are bad practice as they are not needed in the Böhm–Jacopini proof, and thus they advocated that all loops should have a single exit point. This purist approach is embodied in the language [[Pascal (programming language)|Pascal]] (designed in 1968–1969), which up to the mid-1990s was the preferred tool for teaching introductory programming in academia.<ref name="roberts">Roberts, E. [1995] "[http://cs.stanford.edu/people/eroberts/papers/SIGCSE-1995/LoopExits.pdf Loop Exits and Structured Programming: Reopening the Debate] {{Webarchive|url=https://web.archive.org/web/20140725130816/http://cs.stanford.edu/people/eroberts/papers/SIGCSE-1995/LoopExits.pdf |date=2014-07-25 }}," ACM SIGCSE Bulletin, (27)1: 268–272.</ref> The direct application of the Böhm–Jacopini theorem may result in additional local variables being introduced in the structured chart, and may also result in some [[code duplication]].<ref name="WattFindlay2004">{{cite book|author1=David Anthony Watt|author2=William Findlay|title=Programming language design concepts|year=2004|publisher=John Wiley & Sons|isbn=978-0-470-85320-7|page=228}}</ref> Pascal is affected by both of these problems and according to empirical studies cited by [[Eric S. Roberts]], student programmers had difficulty formulating correct solutions in Pascal for several simple problems, including writing a function for searching an element in an array. A 1980 study by Henry Shapiro cited by Roberts found that using only the Pascal-provided control structures, the correct solution was given by only 20% of the subjects, while no subject wrote incorrect code for this problem if allowed to write a return from the middle of a loop.<ref name="roberts"/>
What BÖhm and Jacopini's article showed was that all programs could be goto-free.
Other research showed that control structures with one entry and one exit were
much easier to understand than any other form,
primarily because they could be used anywhere as a statement
without disrupting the control flow.
 
== Control structures in practice ==
Most programming languages with control structures have an initial keyword which indicates the type of control structure involved.{{clarify|date=November 2015}} Languages then divide as to whether or not control structures have a final keyword.
 
* No final keyword: [[ALGOL 60]], [[C (programming language)|C]], [[C++]], [[Go (programming language)|Go]], [[Haskell]], [[Java (programming language)|Java]], [[Pascal (programming language)|Pascal]], [[Perl]], [[PHP]], [[PL/I]], [[Python (programming language)|Python]], [[PowerShell]]. Such languages need some way of grouping statements together:
= Control structures in practice =
** ALGOL 60 and Pascal: <code>begin</code> ... <code>end</code>
** C, C++, Go, Java, Perl, PHP, and PowerShell: [[Curly bracket programming language|curly brackets]] <code>{</code> ... <code>}</code>
** PL/I: <code>DO</code> ... <code>END</code>
** Python: uses [[Indent style|indent]] level (see [[Off-side rule]])
** Haskell: either [[Indent style|indent]] level or curly brackets can be used, and they can be freely mixed
** Lua: uses <code>do</code> ... <code>end</code>
* Final keyword: [[Ada (programming language)|Ada]], [[APL (programming language)|APL]], [[ALGOL 68]], [[Modula-2]], [[Fortran 77]], [[Mythryl]], [[Visual Basic]]. The forms of the final keyword vary:
** Ada: final keyword is <code>end</code> + ''space'' + initial keyword e.g., <code>if</code> ... <code>end if</code>, <code>loop</code> ... <code>end loop</code>
** APL: final keyword is <code>:End</code> optionally + initial keyword, e.g., <code>:If</code> ... <code>:End</code> or <code>:If</code> ... <code>:EndIf</code>, <code>Select</code> ... <code>:End</code> or <code>:Select</code> ... <code>:EndSelect</code>, however, if adding an end condition, the end keyword becomes <code>:Until</code>
** ALGOL 68, Mythryl: initial keyword spelled backwards e.g., <code>if</code> ... <code>fi</code>, <code>case</code> ... <code>esac</code>
** Fortran 77: final keyword is <code>END</code> + initial keyword e.g., <code>IF</code> ... <code>ENDIF</code>, <code>DO</code> ... <code>ENDDO</code>
** Modula-2: same final keyword <code>END</code> for everything
** Visual Basic: every control structure has its own keyword. <code>If</code> ... <code>End If</code>; <code>For</code> ... <code>Next</code>; <code>Do</code> ... <code>Loop</code>; <code>While</code> ... <code>Wend</code>
 
Most programming languages with control structures
have an initial keyword which indicates the type of control structure involved
(Smalltalk is an exception).
Languages then divide as to whether or not control structures have a final keyword.
 
No final keyword: [[Algol programming language|Algol 60]],
[[Pascal programming language|Pascal]], [[C programming language|C]],
[[C plus plus|C++]], [[Java programming language|Java]],
[[PL/I programming language|PL/1]].<br>
Such languages need some way of grouping statements together,
e.g. '''begin''' '''end''' for Algol 60 and Pascal,
curly brackets { } for C, C++, Java.
 
Final keyword: Algol 68, [[Modula-2]], [[Fortran]] (77 onwards).
The forms of the final keyword vary:<br>
Algol 68: initial keyword backwards e.g. '''if''' '''fi''', '''case''' '''esac''',<br>
Modula-2: same final keyword '''end''' for everything (now thought not to be good idea),<br>
Fortran 77: final keyword is '''end''' + initial keyword, IF ENDIF, DO ENDDO
 
Languages which have a final keyword tend to have less debate
regarding layout and indentation.
Languages whose final keyword is of the form: '''end''' + initial keyword
tend to easier to learn.
== Choice ==
=== ChoiceIf-then-(else) using arbitary testsstatements ===
{{main article|Conditional (computer programming)}}
These are usually known as '''if''' statements.
Conditional expressions and conditional constructs are features of a [[programming language]] that perform different computations or actions depending on whether a programmer-specified [[Boolean data type|Boolean]] ''condition'' evaluates to true or false.
Note that if the language has an '''endif''',
* <code>IF..GOTO</code>. A form found in unstructured languages, mimicking a typical machine code instruction, would jump to (GOTO) a label or line number when the condition was met.
then it usually has '''elseif''' as well,
* <code>IF..THEN..(ENDIF)</code>. Rather than being restricted to a jump, any simple statement, or nested block, could follow the THEN key keyword. This a structured form.
in order to avoid a large number of '''endif'''s for multiple tests.
* <code>IF..THEN..ELSE..(ENDIF)</code>. As above, but with a second action to be performed if the condition is false. This is one of the most common forms, with many variations. Some require a terminal <code>ENDIF</code>, others do not. [[C (programming language)|C]] and related languages do not require a terminal keyword, or a 'then', but do require parentheses around the condition.
'''if''' test '''then''' statementTrue '''else''' statementFalse;
* Conditional statements can be and often are nested inside other conditional statements. Some languages allow <code>ELSE</code> and <code>IF</code> to be combined into <code>ELSEIF</code>, avoiding the need to have a series of <code>ENDIF</code> or other final statements at the end of a compound statement.
 
'''if''' (test) statementTrue '''else''' statementFalse;
 
{| class="wikitable"
'''if''' (test1) statementTrue1
|-
'''else''' '''if''' (test2) statement2True
! [[Pascal (programming language)|Pascal]]:
'''else''' '''if''' (test3) statement3True
! [[Ada (programming language)|Ada]]:
'''else''' statementAllFalse;
|-
|<syntaxhighlight lang="pascal">
if a > 0 then
writeln("yes")
else
writeln("no");
</syntaxhighlight>
|<syntaxhighlight lang="ada">
if a > 0 then
Put_Line("yes");
else
Put_Line("no");
end if;
</syntaxhighlight>
|-
! [[C (programming language)|C]]:
! [[Shell script]]:
|-
|<syntaxhighlight lang="c">
if (a > 0) {
puts("yes");
}
else {
puts("no");
}
</syntaxhighlight>
|<syntaxhighlight lang="bash">
if [ $a -gt 0 ]; then
echo "yes"
else
echo "no"
fi
</syntaxhighlight>
|-
! [[Python (programming language)|Python]]:
! [[Lisp (programming language)|Lisp]]:
|-
|<syntaxhighlight lang="python">
if a > 0:
print("yes")
else:
print("no")
</syntaxhighlight>
|<syntaxhighlight lang="lisp">
(princ
(if (plusp a)
"yes"
"no"))
</syntaxhighlight>
|}
Less common variations include:
* Some languages, such as early [[Fortran]],{{efn|In Fortran, this statement was deemed obsolescent in Fortran-90, and deleted as of Fortran 2018.}} have a ''three-way'' or ''[[arithmetic if]]'', testing whether a numeric value is negative, zero, or positive.
*Some languages have a [[Functional programming|functional]] form of an <code>if</code> statement, for instance [[Lisp (programming language)|Lisp's]] <code>cond</code>.
*Some languages have an [[Operator (programming)|operator]] form of an <code>if</code> statement, such as C's [[ternary operator]].
* [[Perl]] supplements a C-style <code>if</code> with <code>when</code> and <code>unless</code>.
* [[Smalltalk]] uses <code>ifTrue</code> and <code>ifFalse</code> messages to implement conditionals, rather than any fundamental language construct.
 
=== Case and switch statements ===
IF (test1) THEN
{{Main article|Switch statement}}
xxx1True
[[Switch statement]]s (or ''case statements'', or ''multiway branches'') compare a given value with specified constants and take action according to the first constant to match. There is usually a provision for a default action ("else", "otherwise") to be taken if no match succeeds. Switch statements can allow compiler optimizations, such as [[lookup table]]s. In [[dynamic language]]s, the cases may not be limited to constant expressions, and might extend to [[pattern matching]], as in the [[shell script]] example on the right, where the <code>*)</code> implements the default case as a [[glob (programming)|glob]] matching any string. Case logic can also be implemented in functional form, as in [[SQL]]'s <code>decode</code> statement.<!--Perl's implementation of case as a lookup table-->
ELSEIF (test2) THEN
xxx2True
ELSEIF (test3) THEN
xxx3True
ELSE
xxxAllFalse
ENDIF
 
{| class="wikitable"
=== Choice based on specific constant values ===
|-
These are usually known as '''case''' or '''switch''' statements.
! [[Pascal (programming language)|Pascal]]:
The effect is to compare a given value with specified constants
! [[Ada (programming language)|Ada]]:
and take action according to the first constant to match.
|-
If the constants form a compact range then this can be implemented
|<syntaxhighlight lang="pascal">
very efficiently as if it were a choce based on whole numbers.
'''case''' someChar '''of''' '''switch''' (someChar) {
'a': actionOnA; '''case''' 'a': actionOnA;
'x': actionOnX; break;
'y','z':actionOnYandZ; '''case''' 'x': actionOnX;
else actionOnNoMatch;
'''end'''; break;
end;
'''case''' 'y':
</syntaxhighlight>
'''case''' 'z': actionOnYandZ;
|<syntaxhighlight lang="ada">
break;
case someChar is
'''default''': actionOnNoMatch;
when 'a' => actionOnA;
}
when 'x' => actionOnX;
=== Choice based on whole numbers 1..N ===
when 'y' | 'z' => actionOnYandZ;
Relatively few programming languages have these constructions
when others => actionOnNoMatch;
but it can be implemented very efficiently using a ''computed goto''.
end;
GOTO (label1,label2,label3), I
</syntaxhighlight>
outOfRangeAction
|-
! [[C (programming language)|C]]:
! [[Shell script]]:
|-
|<syntaxhighlight lang="c">
switch (someChar) {
case 'a': actionOnA; break;
case 'x': actionOnX; break;
case 'y':
case 'z': actionOnYandZ; break;
default: actionOnNoMatch;
}
</syntaxhighlight>
|<syntaxhighlight lang="bash">
case $someChar in
a) actionOnA ;;
x) actionOnX ;;
[yz]) actionOnYandZ ;;
*) actionOnNoMatch ;;
esac
</syntaxhighlight>
|-
! [[Lisp (programming language)|Lisp]]:
! [[Fortran]]:
|-
| <syntaxhighlight lang="lisp">
(case some-char
((#\a) action-on-a)
((#\x) action-on-x)
((#\y #\z) action-on-y-and-z)
(else action-on-no-match))
</syntaxhighlight>
| <syntaxhighlight lang="fortran">
select case (someChar)
case ('a')
actionOnA
case ('x')
actionOnX
case ('y','z')
actionOnYandZ
case default
actionOnNoMatch
end select
</syntaxhighlight>
|}
 
'''case''' I '''in''' action1, action2, action3 '''out''' outOfRangeAction '''esac'''
== Loops ==
[[File:Programmingloops.svg|thumb|basic types of program loops]]
A loop is a sequence of statements which is specified once but which may be carried out several times in succession. The code "inside" the loop (the ''body'' of the loop, shown below as ''xxx'') is obeyed a specified number of times, or once for each of a collection of items (both cases of ''definite iteration''), or until some condition is met (''indefinite iteration''), or [[Infinite loop|infinitely]]. When one of those items is itself also a loop, it is called a "nested loop".<ref>{{Cite web |date=2019-11-25 |title=Nested Loops in C with Examples |url=https://www.geeksforgeeks.org/nested-loops-in-c-with-examples/ |access-date=2024-03-14 |website=GeeksforGeeks |language=en-US}}</ref><ref>{{Cite web |title=Python Nested Loops |url=https://www.w3schools.com/python/gloss_python_for_nested.asp |access-date=2024-03-14 |website=www.w3schools.com |language=en-US}}</ref><ref>{{Cite web |last=Dean |first=Jenna |date=2019-11-22 |title=Nested Loops |url=https://medium.com/swlh/nested-loops-ee1dbb9fc8ab |access-date=2024-03-14 |website=The Startup |language=en}}</ref>
 
Some common situations are not well-handled by these basic control structures, and are generally addressed by early exit from the loop, in the form of a ''break'' from the loop, a ''return'' from the function, or an exception being raised.<ref>{{cite journal
A loop is a sequence of statements
|last=Knuth |first=Donald E.
which is specified once but which may be carried out several times in succession.
|author-link=Donald Knuth
The code "inside" the loop (the ''body'' of the loop, shown below as ''xxx'')
|year=1974
is obeyed a specified number of times,
|title=Structured Programming with <code>go to</code> Statements
or once for each of a collection of items,
|journal=[[ACM Computing Surveys|Computing Surveys]]
or until some condition is met.
|volume=6
|issue=4
|pages=261–301
|doi=10.1145/356635.356640
|citeseerx=10.1.1.103.6084
|s2cid=207630080
}}</ref><ref name="roberts"/>
 
In [[functional programming]] languages, such as [[Haskell]] and [[Scheme (programming language)|Scheme]], both [[Recursion (computer science)|recursive]] and [[Fixed point combinator|iterative]] processes are expressed with [[Tail recursion|tail recursive]] procedures instead of looping constructs that are syntactic.
A few languages do not have any constructions for looping
(e.g. [[Lisp programming language|Lisp]] [[Scheme programming language|Scheme]])
and use [[tail recursion]] instead.
 
=== Count-controlled loops ===
{{main article|For loop}}
Most programming languages have constructions for repeating a loop a certain number of times.
In most cases counting can go downwards instead of upwards and step sizes other than 1 can be used.
Note that if N is less than 1 in these examples
then the body is skipped completely.
In most cases counting can go downwards instead of upwards
and step sizes other than 1 can be used.
FOR I = 1 TO N '''for''' I := 1 '''to''' N '''do''' '''begin'''
xxx xxx
NEXT I '''end''';
 
{|
DO I = 1,N '''for''' ( I=1; I<=N; ++I ) {
| {{sxhl|2=basic|1=<nowiki/>
xxx xxx
FOR I = 1 TO N
END DO }
xxx
NEXT I}}
|
'''for''' I := 1 '''to''' N '''do''' '''begin'''
xxx
'''end''';
|-
| {{sxhl|2=fortran|1=<nowiki/>
DO I = 1,N
xxx
END DO}}
|
'''for''' ( I=1; I<=N; ++I ) {
xxx
}
|}
 
In these examples, if N < 1 then the body of loop may execute once (with I having value 1) or not at all, depending on the programming language.
See also [[For loop]].
 
In many programming languages, only integers can be reliably used in a count-controlled loop. Floating-point numbers are represented imprecisely due to hardware constraints, so a loop such as
 
'''for''' X := 0.1 '''step''' 0.1 '''to''' 1.0 '''do'''
 
might be repeated 9 or 10 times, depending on rounding errors and/or the hardware and/or the compiler version. Furthermore, if the increment of X occurs by repeated addition, accumulated rounding errors may mean that the value of X in each iteration can differ quite significantly from the expected sequence 0.1, 0.2, 0.3, ..., 1.0.
 
=== Condition-controlled loops ===
{{main article|While loop|Do while loop}}
Again, most programming languages have constructions
Most programming languages have constructions for repeating a loop until some condition changes. Some variations test the condition at the start of the loop; others test it at the end. If the test is at the start, the body may be skipped completely; if it is at the end, the body is always executed at least once.
for repeating a loop until some condition changes.
Note that some variations place the test at the start of the loop,
while others have the test at the end of the loop.
In the former case the body may be skipped completely,
while in the latter case the body is always obeyed at least once.
DO WHILE (test) '''repeat'''
xxx xxx
END DO '''until''' test;
 
{| class="wikitable"
'''while''' (test) { '''do'''
|
xxx xxx
DO WHILE (test)
} '''while''' (test);
xxx
LOOP
|
'''repeat'''
xxx
'''until''' test;
|-
|
'''while''' (test) {
xxx
}
|
'''do'''
xxx
'''while''' (test);
|}
 
A [[control break]] is a value change detection method used within ordinary loops to trigger processing for groups of values. Values are monitored within the loop and a change diverts program flow to the handling of the group event associated with them.
See also [[While loop]].
 
DO UNTIL (End-of-File)
IF new-zipcode <> current-zipcode
display_tally(current-zipcode, zipcount)
current-zipcode = new-zipcode
zipcount = 0
ENDIF
zipcount++
LOOP
 
=== Collection-controlled loops ===
{{main article|Foreach loop|l1=Foreach}}
A few programming languages (e.g. [[Perl]] [[Smalltalk]])
Several programming languages (e.g., [[Ada (programming language)|Ada]], [[APL (programming language)|APL]], [[D (programming language)|D]], [[C++11]], [[Smalltalk]], [[PHP]], [[Perl]], [[Object Pascal]], [[Java (programming language)|Java]], [[C Sharp (programming language)|C#]], [[MATLAB]], [[Visual Basic]], [[Ruby (programming language)|Ruby]], [[Python (programming language)|Python]], [[JavaScript]], [[Fortran 95]] and later) have special constructs which allow implicit looping through all elements of an array, or all members of a set or collection.
have special constructs which allow you to implicitly loop through
all elements of an array, or all members of a set or collection.
someCollection '''do''': [ :eachElement | xxx ].
 
someCollection '''do''': {{codett|2=smalltalk|[:eachElement {{!}}xxx]. "Smalltalk"}}
'''for''' Item '''in''' Collection '''do''' '''begin''' xxx '''end''';
'''foreach''' (item; myCollection) { xxx }
'''foreach''' someArray { xxx }
'''foreach''' {{codett|2=php|1=($someArray as $k => $v) { xxx } # PHP}}
Collection<String> coll; '''for''' (String s : coll) {}
'''foreach''' ('''string''' s '''in''' myStringCollection) { xxx }
{{codett|2=ps1|someCollection {{!}} foreach { $_ } # Powershell: 'foreach' and '%' are the alias of 'ForEach-Object'}}
'''forall''' ( index = first:last:step... )
 
[[Scala (programming language)|Scala]] has [[Scala (programming language)#For-expressions|for-expressions]], which generalise collection-controlled loops, and also support other uses, such as [[asynchronous programming]]. [[Haskell]] has do-expressions and comprehensions, which together provide similar function to for-expressions in Scala.
 
=== General iteration ===
General iteration constructs such as C's <code>for</code> statement and [[Common Lisp]]'s <code>do</code> form can be used to express any of the above sorts of loops, and others, such as looping over some number of collections in parallel. Where a more specific looping construct can be used, it is usually preferred over the general iteration construct, since it often makes the purpose of the expression clearer.
 
=== Infinite loops ===
{{main article|Infinite loop}}
[[Infinite loop]]s are used to assure a program segment loops forever or until an exceptional condition arises, such as an error. For instance, an event-driven program (such as a [[Server (computing)|server]]) should loop forever, handling events as they occur, only stopping when the process is terminated by an operator.
 
Infinite loops can be implemented using other control flow constructs. Most commonly, in unstructured programming this is jump back up (goto), while in structured programming this is an indefinite loop (while loop) set to never end, either by omitting the condition or explicitly setting it to true, as <code>while (true) ...</code>. Some languages have special constructs for infinite loops, typically by omitting the condition from an indefinite loop. Examples include Ada (<code>loop ... end loop</code>),<ref>[[b:Ada Programming/Control#Endless Loop|Ada Programming: Control: Endless Loop]]</ref> Fortran (<code>DO ... END DO</code>), Go (<code>for { ... }</code>), and Ruby (<code>loop do ... end</code>).
 
Often, an infinite loop is unintentionally created by a programming error in a condition-controlled loop, wherein the loop condition uses variables that never change within the loop.
 
=== Continuation with next iteration ===
Sometimes within the body of a loop there is a desire to skip the remainder of the loop body and continue with the next iteration of the loop. Some languages provide a statement such as <code>continue</code> (most languages), <code>skip</code>,<ref>{{cite web |title=What is a loop and how we can use them? |url=http://www.megacpptutorials.com/2012/12/what-is-loop.html |access-date=2020-05-25 |url-status=dead |archive-date=2020-07-28 |archive-url=https://web.archive.org/web/20200728081722/http://www.megacpptutorials.com/2012/12/what-is-loop.html }}</ref> <code>cycle</code> (Fortran), or <code>next</code> (Perl and Ruby), which will do this. The effect is to prematurely terminate the innermost loop body and then resume as normal with the next iteration. If the iteration is the last one in the loop, the effect is to terminate the entire loop early.
 
=== Redo current iteration ===
Some languages, like Perl<ref>{{cite web|title=redo - perldoc.perl.org|url=https://perldoc.perl.org/functions/redo.html|access-date=2020-09-25|website=perldoc.perl.org}}</ref> and Ruby,<ref>{{cite web|title=control_expressions - Documentation for Ruby 2.4.0|url=https://docs.ruby-lang.org/en/2.4.0/syntax/control_expressions_rdoc.html|access-date=2020-09-25|website=docs.ruby-lang.org}}</ref> have a <code>redo</code> statement that restarts the current iteration from the start.
 
=== Restart loop ===
Ruby has a <code>retry</code> statement that restarts the entire loop from the initial iteration.<ref>{{cite web|title=control_expressions - Documentation for Ruby 2.3.0|url=https://docs.ruby-lang.org/en/2.3.0/syntax/control_expressions_rdoc.html|access-date=2020-09-25|website=docs.ruby-lang.org}}</ref>
 
=== Loop-and-a-half ===
Common loop structures sometimes result in duplicated code, either repeated statements or repeated conditions. This arises for various reasons and has various proposed solutions to eliminate or minimize code duplication.<ref name="c2messy">{{cite web |url=https://wiki.c2.com/?MessyLoopConditions |title=Messy Loop Conditions |work=WikiWikiWeb |date=2014-11-03}}</ref> Other than the traditional unstructured solution of a ''goto'' statement,{{sfn|Knuth|1974|p=278|loc=Simple Iterations}} general structured solutions include having a conditional (''if'' statement) inside the loop (possibly duplicating the condition but not the statements) or wrapping repeated logic in a function (so there is a duplicated function call, but the statements are not duplicated).<ref name="c2messy" />
 
A common case is where the start of the loop is always executed, but the end may be skipped on the last iteration.{{sfn|Knuth|1974|p=278|loc=Simple Iterations}} This was dubbed by Dijkstra a loop which is performed "''n'' and a half times",<ref>[[Edsger W. Dijkstra]], personal communication to [[Donald Knuth]] on 1974-01-03, cited in {{harvtxt|Knuth|1974|p=278|loc=Simple Iterations}}</ref> and is now called the '''''loop-and-a-half''' problem''.<ref name="roberts"/> Common cases include reading data in the first part, checking for end of data, and then processing the data in the second part; or processing, checking for end, and then preparing for the next iteration.{{sfn|Knuth|1974|p=278|loc=Simple Iterations}}<ref name="roberts"/> In these cases, the first part of the loop is executed {{tmath|n}} times, but the second part is only executed {{tmath|n - 1}} times.
 
This problem has been recognized at least since 1967 by Knuth, with Wirth suggesting solving it via early loop exit.{{sfn|Knuth|1974|p=279}} Since the 1990s this has been the most commonly taught solution, using a ''break'' statement, as in:<ref name="roberts"/>
 
 
'''loop'''
''statements''
'''if''' ''condition'' '''break'''
''statements''
'''repeat'''
 
A subtlety of this solution is that the condition is the ''opposite'' of a usual ''while'' condition: rewriting '''while''' ''condition'' ... '''repeat''' with an exit in the middle requires reversing the condition: '''loop''' ... '''if not''' ''condition'' '''exit''' ... '''repeat'''. The [[#Loop with test in the middle|loop with test in the middle]] control structure explicitly supports the loop-an-a-half use case, without reversing the condition.{{sfn|Knuth|1974|p=279}}
 
=== Early exit from loops ===
When using a count-controlled loop to search through a table,
you may wish to stop searching as soon as you have found the required item.
Some programming languages provide a statement such as '''break''' or '''exit''',
whose effect is to terminate the current loop immediately and transfer control
to the statement immediately following that loop.
Things can get a bit messy if you are searching a multi-dimensional table
using nested loops (see Missing Control Structures below).
=== Potential problems with loops ===
Count-controlled loops should always use whole numbers or equivalent,
since a loop such as<br>
'''for''' X := 0.1 '''step''' 0.1 '''to''' 1.0 '''do'''<br>
might be repeated 9 or 10 times,
depending on rounding errors and/or the hardware and/or the compiler version.
 
It is sometimes desirable to stop executing a loop before the end of the body; for example, when using a count-controlled loop to search through a table, one can stop as soon as the required item is found. Early exit is the most common way to solve the [[loop-and-a-half]] problem.<ref name="roberts"/>
Condition-controlled loops rely on the test condition being changed in some way
within the body of the loop; if not, you get an [[infinite loop]].
== Error recovery ==
Most programming languages have some way
in which a program can detect that end-of-file has been reached when reading data,
but very few programming languages have any systematic way of handling the situation
when something goes wrong or something unusual happens.
 
[[PL/I programming language|PL/1]] has some 22 standard conditions
(e.g. ZERODIVIDE SUBSCRIPTRANGE ENDFILE)
which can be RAISEd and which can be intercepted by: ON ''condition'' action;
Programmers can also define and use their own named conditions.
In many cases a GOTO is needed to decide where flow of control should resume.
Unfortunately, some implementations had a substantial overhead in both space and time
(especially SUBSCRIPTRANGE), so many programmers tried to avoid using conditions.
 
Some programming languages provide a statement such as <code>break</code> (most languages), <code>Exit</code> (Visual Basic), or <code>last</code> (Perl), which effect is to terminate the current loop immediately, and transfer control to the statement immediately after that loop.
[[C Plus Plus|C++]] has a special construct for exception handling.
'''try''' {
xxx1 // Somewhere in here
xxx2 // use: '''throw''' someValue;
xxx3
} '''catch''' (someClass & someId) { // catch value of someClass
actionForSomeClass
} '''catch''' (someType & anotherId) { // catch value of someType
actionForSomeType
} '''catch''' (...) { // catch anything not already caught
actionForAnythingElse
}
 
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").
Any number and variety of '''catch''' clauses can be used above.
C++ has a standard list of exceptions
and the circumstances under which they are thrown.
Users may throw and catch almost anything.
If there is no '''catch''' matching a particular '''throw''',
then control percolates back through subroutine calls and/or nested blocks
until a matching '''catch''' is found
or until the end of the main program is reached,
at which point the program is forcibly stopped with a suitable error message.
 
Most commonly, this is used by combining a conditional ('''if''' statement) with an unconditional break, as in Ada:
''Can anyone add something helpful about these or other programming languages?''
== Avoid these constructs ==
Some "features" in programming languages tend to result in (very) unstructured code
and are best avoided. A few of these are listed below.
 
<syntaxhighlight lang="ada">
Very few programming languages have all the control structures mentioned in this article,
loop
so you can reasonably use '''goto''' to emulate the missing structures as required;
Get(X);
see [[Donald Knuth]]'s 1974
if X = 0 then
[http://pplab.snu.ac.kr/courses/PL2001/papers/p261-knuth.pdf article].
exit;
You should not otherwise use '''goto''', due to the risk of creating [[spaghetti code]].
end if;
-- Do something with X.
end loop;
</syntaxhighlight>
 
In this form, the condition is interpreted as '''until'''. Some languages, such as Ada, have syntax for a conditional break, here an '''exit when''' clause (not to be confused with the '''exitwhen''' statement in {{slink||Proposed control structures}}); if available, this is more idiomatic:
For reasons of backwards compatability,
[[Fortran]] still has some arcane unstructured features which should be avoided,
e.g. ASSIGNed GOTO, Arithmetic IF (3-way branch),
Logical IF (2-way branch), labels as parameters.
 
<syntaxhighlight lang="ada">
[[Self-modifying code]], i.e. code which alters itself when executing,
loop
tends to result in very obscure code.
Get(X);
Most assembly languages allow this, as does the ALTER verb in [[COBOL]].
exit when X = 0;
-- 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.
In a spoof [http://www.fortran.com/fortran/come_from.html Datamation article] (December 1973),
R. Lawrence Clark suggested that the GOTO statement
could be replaced by the COMEFROM statement,
and provides some entertaining examples.
This was actually implemented in the [[INTERCAL programming language]],
a language designed to make programs as obscure as 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,
 
<syntaxhighlight lang="python">
= Missing control structures =
for n in set_of_numbers:
if isprime(n):
print("Set contains a prime number")
break
else:
print("Set did not contain any prime numbers")
</syntaxhighlight>
 
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.
In his 1974 [http://pplab.snu.ac.kr/courses/PL2001/papers/p261-knuth.pdf article],
 
[[Donald Knuth]] identified two situations which were not covered
==== Multi-level breaks ====
by the control structures listed above,
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 Ada. 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>
and gave examples of control structures which could handle these situations.
 
Despite their utility, these constructions have not yet found their way
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=https://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.
into main-stream programming languages.
Theory of Computing, (May 1973), 240-252; also in J. Computer and System Sciences, 9,
3 (December 1974), cited by {{harvtxt|Knuth|1974}}.</ref> Furthermore, Kosaraju proved that a strict hierarchy of programs exists: for every integer ''n'', there exists a program containing a multi-level break of depth ''n'' that cannot be rewritten as a program with multi-level breaks of depth less than ''n'' without introducing added variables.<ref name="kozen"/>
 
In his 2004 textbook, [[David Watt (computer scientist)|David Watt]] uses Tennent's notion of [[S-algol|sequencer]] to explain the similarity between multi-level breaks and return statements. Watt notes that a class of sequencers known as ''escape sequencers'', defined as "sequencer that terminates execution of a textually enclosing command or procedure", encompasses both breaks from loops (including multi-level breaks) and return statements. As commonly implemented, however, return sequencers may also carry a (return) value, whereas the break sequencer as implemented in contemporary languages usually cannot.<ref name="WattFindlay2004b">{{cite book|author1=David Anthony Watt|author2=William Findlay| title=Programming language design concepts| year=2004| publisher=John Wiley & Sons|isbn=978-0-470-85320-7|pages=215–221}}</ref>
 
=== Loop with test in the middle ===
The following structure was proposed by [[Ole-Johan Dahl|Dahl]] in 1972:<ref>Dahl & Dijkstra & Hoare, "Structured Programming" Academic Press, 1972.</ref>
 
== Loop with test in the middle ==
This was proposed by [[Ole-Johan_Dahl|Dahl]] in 1972.
'''loop''' '''loop'''
xxx1 read(char);
Line 358 ⟶ 447:
'''repeat'''; '''repeat''';
 
The construction here can be thought of as a '''do''' loop with the '''while''' check in the middle, which allows clear [[#Loop-and-a-half|loop-and-a-half]] logic. Further, by omitting individual components, this single construction can replace several constructions in most programming languages. If ''xxx1'' is omitted, we get a loop with the test at the top (a traditional '''while''' loop). If ''xxx2'' is omitted, we get a loop with the test at the bottom, equivalent to a '''do while''' loop in many languages. If '''while''' is omitted, we get an infinite loop. This construction also allows keeping the same polarity of the condition even when in the middle, unlike early exit, which requires reversing the polarity (adding a '''not'''),{{sfn|Knuth|1974|p=279}} functioning as '''until''' instead of '''while'''.
If ''xxx1'' is omitted we get a loop with the test at the top.
 
If ''xxx2'' is omitted we get a loop with the test at the bottom.
This structure is not widely supported, with most languages instead using '''if''' ... '''break''' for conditional early exit.
If '''while''' is omitted we get an infinite loop.
 
Hence this single construction can replace several constructions in most programming languages.
This is supported by some languages, such as [[Forth (programming language)|Forth]], where the syntax is BEGIN ... WHILE ... REPEAT,<ref>{{Cite web|url=https://www.forth.com/starting-forth/6-forth-do-loops/|title=6. Throw It For a Loop}}</ref> and the [[shell script]] languages [[Bourne shell]] (<code>sh</code>) and [[Bash (Unix shell)|bash]], where the syntax is '''while''' ... '''do''' ... '''done''' or '''until''' ... '''do''' ... '''done''', as:<ref>{{citation |url=https://www.gnu.org/software/bash/manual/bash.html |title=The GNU Bash Reference Manual |section=3.2.5.1 Looping Constructs |section-url=https://www.gnu.org/software/bash/manual/bash.html#Looping-Constructs-1 |date=2025-05-18}}</ref><ref>{{cite web |url=https://langdev.stackexchange.com/questions/1815/how-could-a-language-make-the-loop-and-a-half-less-error-prone/1868#1868 |title=How could a language make the loop-and-a-half less error-prone? |work=Stack Exchange: Programming Language Design and Implementation}}</ref>
A possible variant is to allow more than one '''while''' test; within the loop,
 
but the use of '''exitwhen''' (see next section) appears to cover this case better.
<syntaxhighlight lang="bash">
while
statement-1
statement-2
...
condition
do
statement-a
statement-b
...
done
</syntaxhighlight>
 
The shell syntax works because the '''while''' (or '''until''') loop accepts a list of commands as a condition,<ref>{{citation |url=https://www.gnu.org/software/bash/manual/bash.html |title=The GNU Bash Reference Manual |section=3.2.4 Lists of Commands |section-url=https://www.gnu.org/software/bash/manual/bash.html#Lists |date=2025-05-18}}</ref> formally:
 
'''while''' ''test-commands''; '''do''' ''consequent-commands''; '''done'''
 
The value (exit status) of the list of ''test-commands'' is the value of the ''last'' command, and these can be separated by newlines, resulting in the idiomatic form above.
 
Similar constructions are possible in C and C++ with the [[comma operator]], and [[Comma_operator#Other_languages|other languages with similar constructs]], which allow shoehorning a list of statements into the while condition:
 
<syntaxhighlight lang="c">
while (
statement_1,
statement_2,
condition
) {
statement_a;
statement_b;
}
</syntaxhighlight>
 
While legal, this is marginal, and it is primarily used, if at all, only for short modify-then-test cases, as in:<ref>{{cite web |url=https://stackoverflow.com/questions/52550/what-does-the-comma-operator-do/52615#52615 |title=What does the comma operator , do? |work=[[Stack Overflow]]}}</ref>
 
<syntaxhighlight lang="c">
while (read_string(s), strlen(s) > 0) {
// ...
}
</syntaxhighlight>
 
=== Loop variants and invariants ===
[[Loop variant]]s and [[loop invariant]]s are used to express correctness of loops.<ref>{{cite book| last=Meyer| first=Bertrand| title=Eiffel: The Language| year=1991| publisher=Prentice Hall|pages=129–131}}</ref>
 
In practical terms, a loop variant is an integer expression which has an initial non-negative value. The variant's value must decrease during each loop iteration but must never become negative during the correct execution of the loop. Loop variants are used to guarantee that loops will terminate.
 
A loop invariant is an assertion which must be true before the first loop iteration and remain true after each iteration. This implies that when a loop terminates correctly, both the exit condition and the loop invariant are satisfied. Loop invariants are used to monitor specific properties of a loop during successive iterations.
 
Some programming languages, such as [[Eiffel (programming language)|Eiffel]] contain native support for loop variants and invariants. In other cases, support is an add-on, such as the [[Java Modeling Language]]'s specification for [http://www.eecs.ucf.edu/~leavens/JML//jmlrefman/jmlrefman_12.html#SEC168 loop statements] in [[Java (programming language)|Java]].
 
=== Loop sublanguage ===
Some [[Lisp (programming language)|Lisp]] dialects provide an extensive sublanguage for describing Loops. An early example can be found in Conversional Lisp of [[Interlisp]]. [[Common Lisp]]<ref>{{cite web|title=Common Lisp LOOP macro| url=http://www.lispworks.com/documentation/HyperSpec/Body/m_loop.htm}}</ref> provides a Loop macro which implements such a sublanguage.
 
=== Loop system cross-reference table ===<!-- See also Category:Programming language comparisons. -->
 
{| class="wikitable"
|-
! rowspan=2 |[[Programming language]]
! colspan=3 | conditional
! colspan=4 | loop
! rowspan=2 | early exit
! rowspan=2 | loop continuation
! rowspan=2 | redo
! rowspan=2 | retry
! colspan=2 | correctness facilities
|-
! begin
! middle
! end
! count
! collection
! general
! infinite {{ref_label|loop_infinite|1|a}}
! variant
! invariant
|-
| [[Ada (programming language)|Ada]]
| {{yes}}
| {{yes}}
| {{yes}}
| {{yes}}
| {{partial|arrays}}
| {{no}}
| {{yes}}
| {{yes|deep nested}}
| {{no}}
|
|
|
|
|-
| [[APL (programming language)|APL]]
| {{yes}}
| {{no}}
| {{yes}}
| {{yes}}
| {{yes}}
| {{yes}}
| {{yes}}
| {{partial|deep nested}} {{ref_label|deep_break_c|3|a}}
| {{yes}}
| {{no}}
| {{no}}
|
|
|-
| [[C (programming language)|C]]
| {{yes}}
| {{no}}
| {{yes}}
| {{no}} {{ref_label|loop_for|2|a}}
| {{no}}
| {{yes}}
| {{no}}
| {{partial|deep nested}} {{ref_label|deep_break_c|3|a}}
| {{partial|deep nested}} {{ref_label|deep_break_c|3|a}}
| {{no}}
|
|
|
|-
| [[C++]]
| {{yes}}
| {{no}}
| {{yes}}
| {{no}} {{ref_label|loop_for|2|b}}
| {{yes}} {{ref_label|loop_foreach|9|a}}
| {{yes}}
| {{no}}
| {{partial|deep nested}} {{ref_label|deep_break_c|3|b}}
| {{partial|deep nested}} {{ref_label|deep_break_c|3|a}}
| {{no}}
|
|
|
|-
| [[C Sharp (programming language)|C#]]
| {{yes}}
| {{no}}
| {{yes}}
| {{no}} {{ref_label|loop_for|2|c}}
| {{yes}}
| {{yes}}
| {{no}}
| {{partial|deep nested}} {{ref_label|deep_break_c|3|c}}
| {{partial|deep nested}} {{ref_label|deep_break_c|3|a}}
|
|
|
|
|-
| [[COBOL]]
| {{yes}}
| {{no}}
| {{yes}}
| {{yes}}
| {{no}}
| {{yes}}
| {{no}}
| {{partial|deep nested}} {{ref_label|cobol_deep_exit|15|a}}
| {{partial|deep nested}} {{ref_label|cobol_deep_exit|14|a}}
| {{no}}
|
|
|
|-
| [[Common Lisp]]
| {{yes}}
| {{yes}}
| {{yes}}
| {{yes}}
| {{partial|builtin only}} {{ref_label|cl_sequence_type|16|a}}
| {{yes}}
| {{yes}}
| {{yes|deep nested}}
| {{no}}
|
|
|
|
|-
| [[D (programming language)|D]]
| {{yes}}
| {{no}}
| {{yes}}
| {{yes}}
| {{yes}}
| {{yes}}
| {{yes}}{{ref_label|DInfinite|14|a}}
| {{yes|deep nested}}
| {{yes|deep nested}}
| {{no}}
|
|
|
|-
| [[Eiffel (programming language)|Eiffel]]
| {{yes}}
| {{no}}
| {{no}}
| {{yes}} {{ref_label|count_loop_eiffel|10|a}}
| {{yes}}
| {{yes}}
| {{no}}
| {{partial|one level}} {{ref_label|count_loop_eiffel|10|a}}
| {{no}}
| {{no}}
| {{no}} {{ref_label|retry_in_eiffel|11|a}}
| {{partial|integer only}} {{ref_label|integer_variant|13|a}}
| {{yes}}
|-
| [[F Sharp (programming language)|F#]]
| {{yes}}
| {{no}}
| {{no}}
| {{yes}}
| {{yes}}
| {{no}}
| {{no}}
| {{no}} {{ref_label|deep_break_e|6|b}}
| {{no}}
| {{no}}
|
|
|
|-
| [[FORTRAN 77]]
| {{yes}}
| {{no}}
| {{no}}
| {{yes}}
| {{no}}
| {{no}}
| {{no}}
| {{partial|one level}}
| {{yes }}
| {{no}}
| {{no}}
|
|
|-
| [[Fortran 90]]
| {{yes}}
| {{no}}
| {{no}}
| {{yes}}
| {{no}}
| {{no}}
| {{yes}}
| {{yes|deep nested}}
| {{yes|deep nested}}
| {{no}}
| {{no}}
|
|
|-
| [[Fortran 95]] and later
| {{yes}}
| {{no}}
| {{no}}
| {{yes}}
| {{partial|arrays}}
| {{no}}
| {{yes}}
| {{yes|deep nested}}
| {{yes|deep nested}}
| {{no}}
| {{no}}
|
|
|-
| [[Go (programming language)|Go]]
| {{yes}}
| {{no}}
| {{no}}
| {{yes}}
| {{partial|builtin only}}
| {{yes}}
| {{yes}}
| {{yes|deep nested}}
| {{yes|deep nested}}
| {{no}}
|
|
|
|-
| [[Haskell]]
| {{no}}
| {{no}}
| {{no}}
| {{no}}
| {{yes}}
| {{no}}
| {{yes}}
| {{no}} {{ref_label|deep_break_e|6|a}}
| {{no}}
| {{no}}
|
|
|
|-
| [[Java (programming language)|Java]]
| {{yes}}
| {{no}}
| {{yes}}
| {{no}} {{ref_label|loop_for|2|d}}
| {{yes}}
| {{yes}}
| {{no}}
| {{yes|deep nested}}
| {{yes|deep nested}}
| {{no}}
|
|{{yes|non-native}} {{ref_label|requires_JML|12|a}}
|{{yes|non-native}} {{ref_label|requires_JML|12|a}}
|-
| [[JavaScript]]
| {{yes}}
| {{no}}
| {{yes}}
| {{no}} {{ref_label|loop_for|2|g}}
| {{yes}}
| {{yes}}
| {{no}}
| {{yes|deep nested}}
| {{yes|deep nested}}
| {{no}}
|
|
|-
| Natural
| {{yes}}
| {{yes}}
| {{yes}}
| {{yes}}
| {{no}}
| {{yes}}
| {{yes}}
| {{yes}}
| {{yes}}
| {{yes}}
| {{no}}
|
|-
| [[OCaml]]
| {{yes}}
| {{no}}
| {{no}}
| {{yes}}
| {{yes|arrays,lists}}
| {{no}}
| {{no}}
| {{no}} {{ref_label|deep_break_e|6|b}}
| {{no}}
| {{no}}
|
|
|
|-
| [[PHP]]
| {{yes}}
| {{no}}
| {{yes}}
| {{no}} {{ref_label|loop_for|2|e}} {{ref_label|loop_for|5|b}}
| {{yes}} {{ref_label|loop_phpforeach|4|a}}
| {{yes}}
| {{no}}
| {{yes|deep nested}}
| {{yes|deep nested}}
| {{no}}
|
|
|
|-
| [[Perl]]
| {{yes}}
| {{no}}
| {{yes}}
| {{no}} {{ref_label|loop_for|2|f}} {{ref_label|loop_for|5|c}}
| {{yes}}
| {{yes}}
| {{no}}
| {{yes|deep nested}}
| {{yes|deep nested}}
| {{yes}}
|
|
|
|-
| [[Python (programming language)|Python]]
| {{yes}}
| {{no}}
| {{no}}
| {{no}} {{ref_label|loop_range|5|a}}
| {{yes}}
| {{no}}
| {{no}}
| {{partial|deep nested}} {{ref_label|deep_break_e|6|c}}
| {{partial|deep nested}} {{ref_label|deep_break_e|6|c}}
| {{no}}
|
|
|
|-
| [[Rebol]]
| {{no}} {{ref_label|while|7|a}}
| {{yes}}
| {{yes}}
| {{yes}}
| {{yes}}
| {{no}} {{ref_label|user|8|a}}
| {{yes}}
| {{partial|one level}} {{ref_label|deep_break_e|6|d}}
| {{no}}
| {{no}}
|
|
|
|-
| [[Ruby (programming language)|Ruby]]
| {{yes}}
| {{no}}
| {{yes}}
| {{yes}}
| {{yes}}
| {{no}}
| {{yes}}
| {{partial|deep nested}} {{ref_label|deep_break_e|6|e}}
| {{partial|deep nested}} {{ref_label|deep_break_e|6|e}}
| {{yes}}
| {{yes}}
|
|
|-
| [[Standard ML]]
| {{yes}}
| {{no}}
| {{no}}
| {{no}}
| {{yes|arrays,lists}}
| {{no}}
| {{no}}
| {{no}} {{ref_label|deep_break_e|6|b}}
| {{no}}
| {{no}}
|
|
|
|-
| [[Visual Basic .NET]]
| {{yes}}
| {{no}}
| {{yes}}
| {{yes}}
| {{yes}}
| {{no}}
| {{yes}}
| {{partial|one level per type of loop}}
| {{partial|one level per type of loop}}
|
|
|
|
|-
| [[PowerShell]]
| {{yes}}
| {{no}}
| {{yes}}
| {{no}} {{ref_label|loop_for|2|h}}
| {{yes}}
| {{yes}}
| {{no}}
| {{yes}}
| {{yes}}
|
|
|
|
|}
# {{note label|loop_infinite|1|a}} <code>while (true)</code> does not count as an infinite loop for this purpose, because it is not a dedicated language structure.
# {{note label|loop for|2|a}}{{note_label|loop_for|2|b}}{{note_label|loop_for|2|c}}{{note_label|loop_for|2|d}}{{note_label|loop_for|2|e}}{{note_label|loop_for|2|f}}{{note_label|loop_for|2|g}}{{note_label|loop_for|2|h}} C's <code>for (''init''; ''test''; ''increment'')</code> loop is a general loop construct, not specifically a counting one, although it is often used for that.
# {{note label|deep_break_c|3|a}}{{note label|deep_break_c|3|b}}{{note label|deep_break_c|3|c}} Deep breaks may be accomplished in APL, C, C++ and C# through the use of labels and gotos.
# {{note label|loop_phpforeach|4|a}} Iteration over objects was [http://www.php.net/manual/en/language.oop5.iterations.php added] in PHP 5.
# {{note label|loop_range|5|a}}{{note label|loop_range|5|b}}{{note label|loop_range|5|c}} A counting loop can be simulated by iterating over an incrementing list or generator, for instance, Python's <code>range()</code>.
# {{note label|deep_break_e|6|a}}{{note label|deep_break_e|6|b}}{{note label|deep_break_e|6|c}}{{note label|deep_break_e|6|d}}{{note label|deep_break_e|6|e}} Deep breaks may be accomplished through the use of exception handling.
# {{note_label|while|7|a}} There is no special construct, since the <code>while</code> function can be used for this.
# {{note_label|user|8|a}} There is no special construct, but users can define general loop functions.
# {{note_label|loop_foreach|9|a}} The [[C++11]] standard introduced the [[C++11#Range-based for loop|range-based for]]. In the [[Standard Template Library|STL]], there is a <code>std::for_each</code> [[template (programming)|template]] function which can iterate on STL [[Container (data structure)|containers]] and call a [[unary function]] for each element.<ref>[http://www.sgi.com/tech/stl/for_each.html for_each]. Sgi.com. Retrieved on 2010-11-09.</ref> The functionality also can be constructed as [[C preprocessor#Macro definition and expansion|macro]] on these containers.<ref>[https://boost-sandbox.sourceforge.net/libs/foreach/doc/html/ Chapter 1. Boost.Foreach] {{Webarchive|url=https://web.archive.org/web/20100129070613/http://boost-sandbox.sourceforge.net/libs/foreach/doc/html/ |date=2010-01-29}}. Boost-sandbox.sourceforge.net (2009-12-19). Retrieved on 2010-11-09.</ref>
# {{note_label|count_loop_eiffel|10|a}} Count-controlled looping is effected by iteration across an integer interval; early exit by including an additional condition for exit.
# {{note_label|retry_in_eiffel|11|a}} Eiffel supports a reserved word <code>retry</code>, however it is used in [[Exception handling#Exception handling based on design by contract|exception handling]], not loop control.
# {{note_label|requires_JML|12|a}} Requires [[Java Modeling Language]] (JML) behavioral interface specification language.
# {{note_label|integer_variant|13|a}} Requires loop variants to be integers; transfinite variants are not supported. [http://archive.eiffel.com/doc/faq/variant.html Eiffel: Why loop variants are integers]
# {{note_label|DInfinite|13|a}} D supports infinite collections, and the ability to iterate over those collections. This does not require any special construct.
# {{note_label|cobol_deep_exit|14|a}} Deep breaks can be achieved using <code>GO TO</code> and procedures.
# {{note_label|cl_sequence_type|14|a}} Common Lisp predates the concept of generic collection type.
 
== Structured non-local control flow ==
Many programming languages, especially those favoring more dynamic styles of programming, offer constructs for ''non-local control flow''. These cause the flow of execution to jump out of a given context and resume at some [[predeclared]] point. ''[[Exception handling#Condition systems|Conditions]]'', ''[[Exception handling|exceptions]]'' and ''[[continuation]]s'' are three common sorts of non-local control constructs; more exotic ones also exist, such as [[Generator (computer programming)|generators]], [[coroutine]]s and the [[Futures and promises|async]] keyword.
 
=== Conditions ===
The earliest [[Fortran]] compilers had statements for testing exceptional conditions. These included the <code>IF ACCUMULATOR OVERFLOW</code>, <code>IF QUOTIENT OVERFLOW</code>, and <code>IF DIVIDE CHECK</code> statements. In the interest of machine independence, they were not included in FORTRAN IV and the Fortran 66 Standard. However since Fortran 2003 it is possible to test for numerical issues via calls to functions in the <code>IEEE_EXCEPTIONS</code> module.
 
[[PL/I]] has some 22 standard conditions (e.g., ZERODIVIDE SUBSCRIPTRANGE ENDFILE) which can be raised and which can be intercepted by: ON ''condition'' action; Programmers can also define and use their own named conditions.
 
Like the ''unstructured if'', only one statement can be specified so in many cases a GOTO is needed to decide where flow of control should resume.
 
Unfortunately, some implementations had a substantial overhead in both space and time (especially SUBSCRIPTRANGE), so many programmers tried to avoid using conditions.
 
Common Syntax examples:
 
'''ON''' ''condition'' '''GOTO''' ''label''
 
=== Exceptions ===
{{main article|Exception handling}}
Modern languages have a specialized structured construct for exception handling which does not rely on the use of <code>GOTO</code> or (multi-level) breaks or returns. For example, in C++ one can write:
 
<syntaxhighlight lang="cpp">
try {
xxx1 // Somewhere in here
xxx2 // use: '''throw''' someValue;
xxx3
} catch (someClass& someId) { // catch value of someClass
actionForSomeClass
} catch (someType& anotherId) { // catch value of someType
actionForSomeType
} catch (...) { // catch anything not already caught
actionForAnythingElse
}
</syntaxhighlight>
 
Any number and variety of <code>catch</code> clauses can be used above. If there is no <code>catch</code> matching a particular <code>throw</code>, control percolates back through subroutine calls and/or nested blocks until a matching <code>catch</code> is found or until the end of the main program is reached, at which point the program is forcibly stopped with a suitable error message.
 
Via C++'s influence, <code>catch</code> is the keyword reserved for declaring a pattern-matching exception handler in other languages popular today, like Java or C#. Some other languages like Ada use the keyword <code>exception</code> to introduce an exception handler and then may even employ a different keyword (<code>when</code> in Ada) for the pattern matching. A few languages like [[AppleScript]] incorporate placeholders in the exception handler syntax to automatically extract several pieces of information when the exception occurs. This approach is exemplified below by the <code>on error</code> construct from AppleScript:<!-- Here, it would help to explain what all those "from", "to", and "partial results" bits do.-->
 
<syntaxhighlight lang = "applescript">
try
set myNumber to myNumber / 0
on error e number n from f to t partial result pr
if ( e = "Can't divide by zero" ) then display dialog "You must not do that"
end try
</syntaxhighlight>
 
David Watt's 2004 textbook also analyzes exception handling in the framework of sequencers (introduced in this article in the section on early exits from loops). Watt notes that an abnormal situation, generally exemplified with arithmetic overflows or [[input/output]] failures like file not found, is a kind of error that "is detected in some low-level program unit, but [for which] a handler is more naturally located in a high-level program unit". For example, a program might contain several calls to read files, but the action to perform when a file is not found depends on the meaning (purpose) of the file in question to the program and thus a handling routine for this abnormal situation cannot be located in low-level system code. Watts further notes that introducing status flags testing in the caller, as single-exit structured programming or even (multi-exit) return sequencers would entail, results in a situation where "the application code tends to get cluttered by tests of status flags" and that "the programmer might forgetfully or lazily omit to test a status flag. In fact, abnormal situations represented by status flags are by default ignored!" Watt notes that in contrast to status flags testing, exceptions have the opposite [[Default (computer science)|default behavior]], causing the program to terminate unless the program deals with the exception explicitly in some way, possibly by adding explicit code to ignore it. Based on these arguments, Watt concludes that jump sequencers or escape sequencers are less suitable as a dedicated exception sequencer with the semantics discussed above.<ref>{{cite book|author1=David Anthony Watt|author2=William Findlay|title=Programming language design concepts|year=2004|publisher=John Wiley & Sons|isbn=978-0-470-85320-7|pages=221–222}}</ref>
 
In Object Pascal, D, Java, C#, and Python a <code>finally</code> clause can be added to the <code>try</code> construct. No matter how control leaves the <code>try</code> the code inside the <code>finally</code> clause is guaranteed to execute. This is useful when writing code that must relinquish an expensive resource (such as an opened file or a database connection) when finished processing:
 
<syntaxhighlight lang="csharp">
FileStream stm = null; // C# example
try
{
stm = new FileStream("logfile.txt", FileMode.Create);
return ProcessStuff(stm); // may throw an exception
}
finally
{
if (stm != null)
stm.Close();
}
</syntaxhighlight>
 
Since this pattern is fairly common, C# has a special syntax:
 
<syntaxhighlight lang="csharp">
using (var stm = new FileStream("logfile.txt", FileMode.Create))
{
return ProcessStuff(stm); // may throw an exception
}
</syntaxhighlight>
 
Upon leaving the <code>using</code>-block, the compiler guarantees that the <code>stm</code> object is released, effectively [[Name binding|binding]] the variable to the file stream while abstracting from the side effects of initializing and releasing the file. Python's <code>with</code> statement and Ruby's block argument to <code>File.open</code> are used to similar effect.
 
All the languages mentioned above define standard exceptions and the circumstances under which they are thrown. Users can throw exceptions of their own; C++ allows users to throw and catch almost any type, including basic types like <code>int</code>, whereas other languages like Java are less permissive.
 
=== Continuations ===
{{main article|Continuation}}
 
=== Async ===
C# 5.0 introduced the async keyword for supporting [[asynchronous I/O]] in a "direct style".
 
=== Generators ===
{{Main|Generator (computer science)}}
[[Generator (computer science)|Generators]], also known as semicoroutines, allow control to be yielded to a consumer method temporarily, typically using a {{Python|yield}} keyword ([https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/yield yield description]) . Like the async keyword, this supports programming in a "direct style".
 
=== Coroutines ===
{{Main|Coroutine}}
[[Coroutines]] are functions that can yield control to each other - a form of [[co-operative multitasking]] without threads.
 
Coroutines can be implemented as a library if the programming language provides either continuations or generators - so the distinction between coroutines and generators in practice is a technical detail.
 
=== Non-local control flow cross reference ===
{| class="wikitable"
|-
! [[Programming language]]
! conditions
! exceptions
! generators/coroutines
! async
|-
| [[Ada (programming language)|Ada]]
| {{no}}
| {{yes}}
| {{dunno}}
| {{dunno}}
|-
| [[APL (programming language)|APL]]
| {{no}}
| {{yes}}
| {{no}}
| {{no}}
|-
| [[C (programming language)|C]]
| {{no}}
| {{no}}
| {{no}}
| {{no}}
|-
| [[C++]]
| {{no}}
| {{yes}}
| {{yes}}
| {{dunno}}
|-
| [[C Sharp (programming language)|C#]]
| {{no}}
| {{yes}}
| {{yes}}
| {{yes}}
|-
| [[COBOL]]
| {{yes}}
| {{yes}}
| {{no}}
| {{no}}
|-
| [[Common Lisp]]
| {{yes}}
| {{no}}
| {{dunno}}
| {{dunno}}
|-
| [[D (programming language)|D]]
| {{no}}
| {{yes}}
| {{yes}}
| {{dunno}}
|-
| [[Eiffel (programming language)|Eiffel]]
| {{no}}
| {{yes}}
| {{dunno}}
| {{dunno}}
|-
| [[Erlang (programming language)|Erlang]]
| {{no}}
| {{yes}}
| {{yes}}
| {{dunno}}
|-
| [[F Sharp (programming language)|F#]]
| {{no}}
| {{yes}}
| {{yes}}
| {{yes}}
|-
| [[Go (programming language)|Go]]
| {{no}}
| {{yes}}
| {{yes}}
| {{dunno}}
|-
| [[Haskell]]
| {{no}}
| {{yes}}
| {{yes}}
| {{no}}
|-
| [[Java (programming language)|Java]]
| {{no}}
| {{yes}}
| {{no}}
| {{no}}
|-
| [[JavaScript]]
| {{dunno}}
| {{yes}}
| {{yes|Yes}}
| {{yes|Yes}}
|-
| [[Objective-C]]
| {{no}}
| {{yes}}
| {{no}}
| {{dunno}}
|-
| [[PHP]]
| {{no}}
| {{yes}}
| {{yes}}
| {{dunno}}
|-
| [[PL/I]]
| {{yes}}
| {{no}}
| {{no}}
| {{no}}
|-
| [[Python (programming language)|Python]]
| {{no}}
| {{yes}}
| {{yes}}
| {{yes}}<ref>{{Cite web|url=https://docs.python.org/3/library/asyncio.html|title=asyncio — Asynchronous I/O|website=Python documentation}}</ref>
|-
| [[Rebol]]
| {{yes}}
| {{yes}}
| {{no}}
| {{dunno}}
|-
| [[Ruby (programming language)|Ruby]]
| {{no}}
| {{yes}}
| {{yes}}
| {{yes|via extension}}<ref>{{cite web|url=https://github.com/socketry/async|title=Socketry/Async|website=[[GitHub]]|date=25 February 2022}}</ref>
|-
| [[Rust (programming language)|Rust]]
| {{no}}
| {{yes}}
| {{yes|experimental}} <ref>{{Cite web|url=https://doc.rust-lang.org/beta/unstable-book/language-features/generators.html|title=generators - The Rust Unstable Book|website=doc.rust-lang.org}}</ref><ref>{{Cite web|url=https://docs.rs/corona/0.4.3/corona/|title=corona - Rust|website=docs.rs}}</ref>
| {{yes}}<ref>{{Cite web|url=https://rust-lang.github.io/async-book/|title=Introduction - Asynchronous Programming in Rust|website=rust-lang.github.io}}</ref>
|-
| [[Scala (programming language)|Scala]]
| {{no}}
| {{yes}}
| {{yes|via experimental extension}}<ref>{{cite web|url=http://storm-enroute.com/coroutines/ |title=Jitsi Meet |publisher=Storm-enroute.com |date= |accessdate=2022-09-07}}</ref>
| {{yes|via experimental extension}}
|-
| [[Tcl]]
| {{yes|via traces}}
| {{yes}}
| {{yes}}
| {{yes|via event loop}}
|-
| [[Visual Basic .NET]]
| {{yes}}
| {{yes}}
| {{no}}
| {{dunno}}
|-
| [[PowerShell]]
| {{no}}
| {{yes}}
| {{no}}
| {{dunno}}
|}
 
== Proposed control structures ==
As the example on the right shows (copying a file one character at a time),
=== COMEFROM ===
there are simple situations where this is exactly the right construction to use
{{main|COMEFROM}}
in order to avoid duplicated code and/or repeated tests.
In a spoof [[Datamation]] article<ref>[http://www.fortran.com/fortran/come_from.html We don't know where to GOTO if we don't know where we've COME FROM. This (spoof) linguistic innovation lives up to all expectations.] {{Webarchive|url=https://web.archive.org/web/20180716171336/http://www.fortran.com/fortran/come_from.html |date=2018-07-16 }} By R. Lawrence Clark* From Datamation, December, 1973</ref> in 1973, R. Lawrence Clark suggested that the GOTO statement could be replaced by the [[COMEFROM]] statement, and provides some entertaining examples. COMEFROM was implemented in one [[esoteric programming language]] named [[INTERCAL]].
 
=== MultipleEvent-based early exit/exit from nested loops ===
[[Zahn's construct|This construct]] was proposed by [[Zahn's construct|Zahn]] in 1974,<ref>Zahn, C. T. "A control statement for natural top-down structured programming" presented at Symposium on Programming Languages, Paris, 1974.</ref> and discussed in {{harvtxt|Knuth|1974}}. A modified version is presented here.
'''exitwhen''' EventA '''or''' EventB '''or''' EventC;
xxx
Line 380 ⟶ 1,223:
 
'''exitwhen''' is used to specify the events which may occur within ''xxx'',
their occurrence is indicated by using the name of the event as a statement. When some event does occur, the relevant action is carried out, and then control passes just after '''{{not a typo|endexit}}'''. This construction provides a very clear separation between determining that some situation applies, and the action to be taken for that situation.
When some event does occur, the relevant action is carried out,
and then control passes just after '''endexit'''.
This construction provides a very clear separation between
determining that some situation applies, and the action to be taken for that situation.
 
'''exitwhen''' is conceptually similar to the[[exception '''try'''/'''catch'''handling]], constructand exceptions or similar constructs are used for this purpose in C++,many languages.
but is likely to be much more efficient
since there is no percolation across subroutine calls and no transfer of arbitary values.
Also, the compiler can check that all specified events do actually occur
and have associated actions.
 
The following simple example involves searching a two-dimensional table for a particular item.
a two-dimensional table for a particular item.
 
'''exitwhen''' found '''or''' missing;
Line 401 ⟶ 1,235:
missing;
'''exits'''
found: print ("item is in table");
missing: print ("item is not in table");
'''endexit''';
 
== Anecdotal evidenceSecurity ==
One way to attack a piece of software is to redirect the flow of execution of a program. A variety of [[control-flow integrity]] techniques, including [[Stack canary|stack canaries]], [[buffer overflow protection]], shadow stacks, and [[Virtual method table|vtable]] pointer verification, are used to defend against these attacks.<ref>{{cite web|url=https://nebelwelt.net/blog/20141007-CFICPSCPIdiffs.html|title=On differences between the CFI, CPS, and CPI properties|last1=Payer|first1=Mathias|author-link1=Mathias Payer |last2=Kuznetsov|first2=Volodymyr|website=nebelwelt.net|access-date=2016-06-01}}</ref><ref>{{cite web|url=http://www.darkreading.com/vulnerabilities---threats/adobe-flash-bug-discovery-leads-to-new-attack-mitigation-method/d/d-id/1323092|title=Adobe Flash Bug Discovery Leads To New Attack Mitigation Method|website=Dark Reading|date=10 November 2015|access-date=2016-06-01}}</ref><ref>{{cite press release|url=http://www.prnewswire.com/news-releases/endgame-to-present-at-black-hat-usa-2016-300267060.html|title=Endgame to Present at Black Hat USA 2016|last=Endgame|website=www.prnewswire.com|access-date=2016-06-01}}</ref>
The following statistics apply to a 6000-line compiler
written in a private language containing the above constructions.
 
== See also ==
There are 10 condition-controlled loops,
{{div col}}
of which 6 have the test at the top, 1 has the test at the bottom,
* [[Branch (computer science)]]
and 3 have the test in the middle.
* [[Control flow analysis|Control-flow analysis]]
 
* [[Control-flow diagram]]
There are 18 '''exitwhen''' statements, 5 with 2 events, 11 with 3 events, and 2 with 4 events.
* [[Control-flow graph]]
When these were first used in the compiler, replacing various flags and tests,
* [[Control table]]
the number of source lines increased by 0.1%,
* [[Coroutine]]
the size of the object code decreased by 3%,
* [[Cyclomatic complexity]]
and the compiler (when compiling itself) was 4% faster.
* [[DRAKON|Drakon-chart]]
Prior to the introduction of '''exitwhen''',
* [[Flowchart]]
4 of the condition-controlled loops had more than one '''while''' test;
and 5 of the count-controlled loops also had a '''while''' test;
 
 
= See also =
* [[Goto]]
* [[Jeroo]], helps learn control structures
* [[Subroutine]]
* [[Main loop]]
* [[Predication_(computer_architecture)|predication]]
* [[Recursion]]
* [[QuicksortScheduling (computing)]]
* [[Spaghetti code]]
* [[Structured programming]]
* [[Functional programmingSubroutine]]
* [[Switch statement]], alters control flow conditionally
* [[Zahn's construct]]
{{div col end}}
 
== Notes ==
{{Notelist}}
 
== References ==
{{Reflist}}
 
== Further reading ==
* Hoare, C. A. R. "Partition: Algorithm 63," "Quicksort: Algorithm 64," and "Find: Algorithm 65." Comm. ACM 4, 321–322, 1961.
 
= =External links ==
{{wikibooks|Ada Programming|Control}}
* [http://www.acm.org/classics/oct95/ Go to statement considered harmful]
{{wikibooks|Computer Programming|Control}}
* [http://pplab.snu.ac.kr/courses/PL2001/papers/p261-knuth.pdf Structured Programming with goto statements]
*{{Commons category-inline}}
* [http://www.fortran.com/fortran/come_from.html A Linguistic Contribution of GOTO-less Programming]
*[https://web.archive.org/web/20070703050443/http://www.acm.org/classics/oct95/ Go To Statement Considered Harmful]
*[https://web.archive.org/web/20180716171336/http://www.fortran.com/fortran/come_from.html A Linguistic Contribution of GOTO-less Programming]
*{{cite web |url= http://pplab.snu.ac.kr/courses/adv_pl05/papers/p261-knuth.pdf |title= Structured Programming with Go To Statements |url-status= dead |archive-url= https://web.archive.org/web/20090824073244/http://pplab.snu.ac.kr/courses/adv_pl05/papers/p261-knuth.pdf |archive-date= 2009-08-24 }}&nbsp;{{small|(2.88&nbsp;MB)}}
*{{cite web|url= http://www.bitsavers.org/pdf/ibm/704/24-6661-2_704_Manual_1955.pdf |title=IBM 704 Manual }}&nbsp;{{small|(31.4&nbsp;MB)}}
 
[[Category:Control flow| ]]
= References =
[[Category:Iteration in programming]]
* Dahl & Dijkstra & Hoare, "Structured Programming" Academic Press, 1972.
[[Category:Programming language comparisons]]
* BÖhm, Jacopini. Flow diagrams, "Turing Machines and Languages with only Two Formation Rules" Communications of the ACM, 9(5):366-371, May 1966.
[[Category:Recursion]]
* Hoare, C. A. R. "Partition: Algorithm 63," "Quicksort: Algorithm 64," and "Find: Algorithm 65." Comm. ACM 4, 321-322, 1961.
<!-- Hidden categories below -->
* Zahn, C. T. "A control statement for natural top-down structured programming" presented at Symposium on Programming Languages, Paris, 1974.
[[Category:Articles with example Ada code]]
[[Category:Articles with example ALGOL 60 code]]
[[Category:Articles with example ALGOL 68 code]]
[[Category:Articles with example C code]]
[[Category:Articles with example C++ code]]
[[Category:Articles with example C Sharp code]]
[[Category:Articles with example D code]]
[[Category:Articles with example Fortran code]]
[[Category:Articles with example Haskell code]]
[[Category:Articles with example Java code]]
[[Category:Articles with example JavaScript code]]
[[Category:Articles with example Lisp (programming language) code]]
[[Category:Articles with example MATLAB/Octave code]]
[[Category:Articles with example Pascal code]]
[[Category:Articles with example Perl code]]
[[Category:Articles with example PHP code]]
[[Category:Articles with example Python (programming language) code]]
[[Category:Articles with example Ruby code]]
[[Category:Articles with example Smalltalk code]]