Control flow: Difference between revisions

From Wikipedia, the free encyclopedia
Jump to navigation Jump to search
imported>Maxeto0910
no sentence
 
 
(One intermediate revision by one other user not shown)
Line 1: Line 1:
{{Short description|Execution order of computer commands}}
{{Short description |How software progresses through its implementation}}
{{Distinguish|Flow control (data)}}
{{Distinguish |Flow control (data)}}
{{Loop constructs}}<!-- DO NOT remove. Discuss navigation concept at [[Talk:Do while loop#Helpbox experiment]] -->
{{Loop constructs}}<!-- DO NOT remove. Discuss navigation concept at [[Talk:Do while loop#Helpbox experiment]] -->
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.
In [[software]], '''control flow''' (or '''flow of control''') describes how [[Execution (computing)|execution]] progresses from one [[command (computing)|command]] to the next. In many contexts, such as [[machine code]] and an [[imperative programming|imperative]] [[programming language]], control progresses sequentially (to the command located immediately after the currently executing command) except when a command transfers control to another point {{endash}} in which case the command is classified as a control flow command. Depending on context, other terms are used instead of ''command''. For example, in machine code, the typical term is ''instruction'' and in an imperative language, the typical term is ''statement''.


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.
Although an imperative language encodes control flow explicitly, languages of other [[programming paradigm]]s are less focused on control flow. A [[declarative programming|declarative]] language specifies desired results without prescribing an order of operations. A [[functional programming language|functional language]] uses both [[language construct]]s and [[function (computer programming)|functions]] to control flow even though they are usually not called control flow statements.


A set of statements is in turn generally structured as a [[Block (programming)|block]], which in addition to grouping, also defines a [[lexical scope]].
For a [[central processing unit]] (CPU) [[instruction set]], a control flow instruction often alters the [[program counter]] and is either an unconditional [[Branch (computer science)|branch]] (a.k.a. jump) or a conditional branch. An alternative approach is [[Predication (computer architecture)|predication]] which conditionally enables instructions instead of branching.


[[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.
An [[Asynchrony (computer programming)|asynchronous]] control flow transfer such as an [[interrupt]] or a [[Signal (computing)|signal]] alters the normal flow of control to a hander before returning control to where it was interrupted.


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.
One way to attack software is to redirect the flow of execution. 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>


== Categories ==
==Structure==
[[File:Maldi informatics figure 7.JPG|thumb|upright=1.3|A [[state diagram]] of a peptide ion mass mapping search process]]
Control flow is closely related to code structure. Control flows along lines defined by structure and the execution rules of a language. This general concept of structure is not be confused with [[structured programming]] which limits structure to sequencing, selection and iteration based on [[block (programming)|block]] organization.
The kinds of control flow statements supported by different languages vary, but can be categorized by their effect:
* 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 ==
===Sequence===
=== Labels ===
Sequential execution is the most basic structure. Although not all code is sequential in nature, imperative code is.
{{main article|Label (computer science)}}
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:
===Label===
A [[Label (programming language)|label]] identifies a position in [[source code]]. Some control flow statements reference a label so that control jumps to the labeled line. Other than marking a position, a label has no other effect.
 
Some languages limit a label to a number which is sometimes called a [[line number]] although that implies the inherent index of the line; not a label. None-the-less, such numeric labels are typically required to increment from top to bottom in a file even if not be sequential. For example, in BASIC:


<syntaxhighlight lang="qbasic">
<syntaxhighlight lang="qbasic">
10 LET X = 3
10 LET X = 3
20 PRINT X
20 PRINT X
30 GOTO 10
</syntaxhighlight>
</syntaxhighlight>


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:
In many languages, a label is an alphanumeric [[identifier]], usually appearing at the start of a line and immediately followed by a colon. For example, the following C code defines a label {{code |Success}} on line 3 which identifies a jump target point at the first statement that follows it; line 4.
 
<syntaxhighlight lang="c" line>
void f(bool ok) {
    if (ok) {
        goto success;
    }
    return;
success:
    printf("OK");
}
</syntaxhighlight>


<syntaxhighlight lang="c">
===Block===
Success: printf("The operation was successful.\n");
Most languages provide for organizing sequences of code as a [[block (programming)|block]]. When used with a control statement, the beginning of a block provides a jump target. For example, in the following C code (which uses curly braces to delimit a block), control jumps from line 1 to 4 if done is false.
 
<syntaxhighlight lang="c" line>
if (done) {
    printf("All done");
} else {
    printf("Still workin' on it");
}
</syntaxhighlight>
</syntaxhighlight>


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.
==Control{{anchor |control-statement}}==
 
Many control commands have been devised for programming languages. This section describes notable constructs; organized by functionality.


=== Goto ===
===Function===
{{main article|GOTO}}
A function provides for control flow in that when called, execution jumps to the start of the function's code and when it completes, control returns the calling point. In the following C code, control jumps from line 6 to 2 in order to call function {{code |foo()}}. Then, after completing the function body (printing "Hi"), control returns to after the call, line 7.
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.


Although the [[Keyword (computing)|keyword]] may either be in upper or lower case depending on the language, it is usually written as:
<syntaxhighlight lang="c" line>
     '''goto''' ''label''
void foo() {
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.
     printf("Hi");
}


Goto statements have been [[considered harmful]] by many computer scientists, notably [[Edsger W. Dijkstra|Dijkstra]].
void bar() {
    foo();
    printf("Done");
}
</syntaxhighlight>


=== Subroutines ===
===Branch===
{{main article|Subroutine}}
A branch command moves the point of execution from the point in the code that contains the command to the point that the command specifies.
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).


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.
====Jump====
A jump command unconditionally branches control to another point in the code, and is the most basic form of controlling the flow of code.


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 a high-level language, this is often provided as a [[goto]] statement. Although the [[Keyword (computing)|keyword]] may be upper or lower case or one or two words depending on the language, it is like: <code>goto ''label''</code>. When control reaches a goto statement, control then jumps to the statement that follows the indicated label. The goto statement is been [[considered harmful]] by many computer scientists; notably [[Edsger W. Dijkstra|Dijkstra]].


=== Sequence ===
====Conditional branch====
{{main article|Structured programming}}
A [[Conditional (computer programming)|conditional]] statement jumps control based on the value of a [[Boolean data type|Boolean]] expression. Common variations include:


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.
; if-goto: Jumps to a label based on a condition; a high-level programming statement that closely mimics a similar used machine code instruction


== Minimal structured control flow ==
; if-then: Rather than being restricted to a jump, a statement or block is executed if the expression is true. In a language that does not include the {{code |then}} keyword, this can be called an if statement.
{{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.
; if-then-else: Like if-then, but with a second action to be performed if the condition is false. In a language that does not include the {{code |then}} keyword, this can be called an if-else statement.


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.)
; Nested: Conditional statements are often nested inside other conditional statements.


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"/>
; Arithmetic if: Early [[Fortran]], had an [[arithmetic if]] (a.k.a. three-way if) that tests whether a numeric value is negative, zero, or positive. This statement was deemed obsolete in Fortran-90, and deleted as of Fortran 2018.


== Control structures in practice ==
; Functional: Some languages have a [[Functional programming|functional]] form; for instance [[Lisp (programming language)|Lisp's]] <code>cond</code>.
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:
; Operator: Some languages have an [[Operator (programming)|operator]] form, such as the [[ternary conditional operator]].
** 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>


== Choice ==
; When and unless: [[Perl]] supplements a C-style {{code |if}} with {{code |when}} and {{code |unless}}.
=== If-then-(else) statements ===
{{main article|Conditional (computer programming)}}
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.
* <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.
* <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.
* <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.
* 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.


{| class="wikitable"
; Messages: [[Smalltalk]] uses <code>ifTrue</code> and <code>ifFalse</code> messages to implement conditionals, rather than a language construct.
|-
 
! [[Pascal (programming language)|Pascal]]:
The following [[Pascal (programming language)|Pascal]] code shows a simple if-then-else. The syntax is similar in [[Ada (programming language)|Ada]]:
! [[Ada (programming language)|Ada]]:
 
|-
<syntaxhighlight lang="pascal">
|<syntaxhighlight lang="pascal">
if a > 0 then
if a > 0 then
   writeln("yes")
   writeln("yes")
Line 112: Line 108:
   writeln("no");
   writeln("no");
</syntaxhighlight>
</syntaxhighlight>
|<syntaxhighlight lang="ada">
 
if a > 0 then
In [[C (programming language)|C]]:
      Put_Line("yes");
 
else
<syntaxhighlight lang="c">
      Put_Line("no");
end if;
</syntaxhighlight>
|-
! [[C (programming language)|C]]:
! [[Shell script]]:
|-
|<syntaxhighlight lang="c">
if (a > 0) {  
if (a > 0) {  
     puts("yes");
     puts("yes");
}
} else {
else {
     puts("no");
     puts("no");
}
}
</syntaxhighlight>
</syntaxhighlight>
|<syntaxhighlight lang="bash">
 
In [[Bash (Unix shell)|bash]]:
 
<syntaxhighlight lang="bash">
if [ $a -gt 0 ]; then
if [ $a -gt 0 ]; then
       echo "yes"
       echo "yes"
Line 138: Line 128:
fi
fi
</syntaxhighlight>
</syntaxhighlight>
|-
 
! [[Python (programming language)|Python]]:
In [[Python (programming language)|Python]]:
! [[Lisp (programming language)|Lisp]]:
 
|-
<syntaxhighlight lang="python">
|<syntaxhighlight lang="python">
if a > 0:  
if a > 0:  
     print("yes")
     print("yes")
Line 148: Line 137:
     print("no")
     print("no")
</syntaxhighlight>
</syntaxhighlight>
|<syntaxhighlight lang="lisp">
 
In [[Lisp (programming language)|Lisp]]:
 
<syntaxhighlight lang="lisp">
(princ
(princ
   (if (plusp a)
   (if (plusp a)
Line 154: Line 146:
       "no"))
       "no"))
</syntaxhighlight>
</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 ===
====Multiway branch====
{{Main article|Switch statement}}
A multiway branch jumps control based on matching values. There is usually a provision for a default action if no match is found. A switch statement 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.
[[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-->
 
The following [[Pascal (programming language)|Pascal]] code shows a relatively simple [[switch statement]]. Pascal uses the {{code |case}} keyword instead of {{code |switch}}.


{| class="wikitable"
<syntaxhighlight lang="pascal">
|-
! [[Pascal (programming language)|Pascal]]:
! [[Ada (programming language)|Ada]]:
|-
|<syntaxhighlight lang="pascal">
case someChar of
case someChar of
   'a': actionOnA;
   'a': actionOnA;
Line 179: Line 160:
end;
end;
</syntaxhighlight>
</syntaxhighlight>
|<syntaxhighlight lang="ada">
 
In [[Ada (programming language)|Ada]]:
 
<syntaxhighlight lang="ada">
case someChar is
case someChar is
   when 'a' => actionOnA;
   when 'a' => actionOnA;
Line 187: Line 171:
end;
end;
</syntaxhighlight>
</syntaxhighlight>
|-
 
! [[C (programming language)|C]]:
In [[C (programming language)|C]]:
! [[Shell script]]:
 
|-
<syntaxhighlight lang="c">
|<syntaxhighlight lang="c">
switch (someChar) {
switch (someChar) {
  case 'a': actionOnA; break;
    case 'a':  
  case 'x': actionOnX; break;
        actionOnA;  
  case 'y':
        break;
  case 'z': actionOnYandZ; break;
    case 'x':  
  default: actionOnNoMatch;
        actionOnX;  
        break;
    case 'y':
    case 'z':  
        actionOnYandZ;
        break;
    default:  
        actionOnNoMatch;
}
}
</syntaxhighlight>
</syntaxhighlight>
|<syntaxhighlight lang="bash">
 
In [[Bash (Unix shell)|Bash]]:
 
<syntaxhighlight lang="bash">
case $someChar in  
case $someChar in  
   a)    actionOnA ;;
   a)    actionOnA ;;
Line 208: Line 201:
esac
esac
</syntaxhighlight>
</syntaxhighlight>
|-
 
! [[Lisp (programming language)|Lisp]]:
In [[Lisp (programming language)|Lisp]]:
! [[Fortran]]:
 
|-
<syntaxhighlight lang="lisp">
| <syntaxhighlight lang="lisp">
(case some-char
(case some-char
   ((#\a)    action-on-a)
   ((#\a)    action-on-a)
Line 219: Line 211:
   (else      action-on-no-match))
   (else      action-on-no-match))
</syntaxhighlight>
</syntaxhighlight>
| <syntaxhighlight lang="fortran">
 
In [[Fortran]]:
 
<syntaxhighlight lang="fortran">
select case (someChar)
select case (someChar)
   case ('a')
   case ('a')
Line 231: Line 226:
end select
end select
</syntaxhighlight>
</syntaxhighlight>
|}


== Loops ==
===Loop{{anchor |loop-statement}}===
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, or until some condition is met, or [[Infinite loop|indefinitely]]. 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>
[[File:Programmingloops.svg|thumb|basic types of program loops]]
A loop is a sequence of statements, loop body, which is executed a number of times based on runtime state. The body is executed once for each item of a collection (''definite iteration''), until a condition is met (''indefinite iteration''), or [[Infinite loop|infinitely]]. A loop inside the loop body 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> Early exit from a loop may be supported via a break statement.<ref>{{cite journal
|last=Knuth |first=Donald E.
|author-link=Donald Knuth
|year=1974
|title=Structured Programming with <code>go to</code> Statements
|journal=[[ACM Computing Surveys|Computing Surveys]]
|volume=6
|issue=4
|pages=261–301
|doi=10.1145/356635.356640
|citeseerx=10.1.1.103.6084
|s2cid=207630080
}}</ref><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>
 
In a [[functional programming]] language, 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.
 
====Numeric====
{{main |For loop}}
A relatively simple yet useful loop iterates over a range of numeric values. A simple form starts at an integer value, ends at a larger integer value and iterates for each integer value between. Often, the increment can be any integer value; even negative to loop from a larger to a smaller value.
 
Example in BASIC:
 
<syntaxhighlight lang="basic">
FOR I = 1 TO N
  xxx
NEXT I
</syntaxhighlight>
 
Example in Pascal:
 
<syntaxhighlight lang="pascal">
for I := 1 to N do begin
  xxx
end;
</syntaxhighlight>
 
Example in Fortran:
 
<syntaxhighlight lang="fortran">
DO I = 1,N
    xxx
END DO
</syntaxhighlight>
 
In many programming languages, only integers can be used at all or reliably. As a floating-point number is represented imprecisely due to hardware constraints, the following loop might iterate 9 or 10 times, depending on various factors such as rounding error, hardware, compiler. 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 commonly expected sequence of 0.1, 0.2, 0.3, ..., 1.0.
 
'''for''' X := 0.1 '''step''' 0.1 '''to''' 1.0 '''do'''
 
====Condition-controlled====
{{main |While loop |Do while loop}}
Some loop constructs iterate until a condition is true. Some variations test the condition at the start of the loop; others test at the end. If the test is at the start, the body may be skipped completely. At the end, the body is always executed at least once.
 
Example in Visual Basic:
 
<syntaxhighlight lang="visualbasic">
DO WHILE (test)
    xxx
LOOP
</syntaxhighlight>
 
Example in Pascal:
 
<syntaxhighlight lang="pascal">
repeat
    xxx
until test;
</syntaxhighlight>
 
Example in C family of pre-test:


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.
<syntaxhighlight lang="c">
while (test) {
    xxx
}
</syntaxhighlight>


=== Count-controlled loops ===
Example in C family of post-test:
{{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.


{| class="wikitable"
<syntaxhighlight lang="c">
|
do
FOR I = 1 TO N
     xxx
     xxx
NEXT I
while (test);
|
</syntaxhighlight>
'''for''' I := 1 '''to''' N '''do''' '''begin'''
 
Although using the {{code |for}} keyword, the 3-part, c-style loop is condition-based; not a numeric-based construct. The condition, 2nd part, is evaluated before each loop so the loop is pre-test. The 1st part is a place to initialize state and the 3rd part is for incrementing for the next iteration, but both aspects can be performed elsewhere. The following C code implements the logic of a numeric loop that iterates for i from 0 to n-1.
 
<syntaxhighlight lang="c">
for (int i = 0; i < n; ++i) {
     xxx
     xxx
'''end''';
}
|-
</syntaxhighlight>
|
 
DO I = 1,N
====Enumeration====
    xxx
{{main |Foreach loop|l1=Foreach}}
END DO
Some loop constructs enumerate the items of a collection; iterating for each item.
|
 
'''for''' ( I=1; I<=N; ++I ) {
Example in Smalltalk:
    xxx
 
}
<syntaxhighlight lang="smalltalk">
|}
someCollection do: [:eachElement |xxx].
</syntaxhighlight>
 
Example in Pascal:
 
<syntaxhighlight lang="pascal">
for Item in Collection do begin xxx end;
</syntaxhighlight>
 
Example in Raku:
 
<syntaxhighlight lang="raku">
foreach (item; myCollection) { xxx }
</syntaxhighlight>
 
Example in TCL:
 
<syntaxhighlight lang="tcl">
foreach someArray { xxx }
</syntaxhighlight>
 
Example in PHP:
 
<syntaxhighlight lang="php">
foreach ($someArray as $k => $v) { xxx }
</syntaxhighlight>


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.
Example in Java:


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<br />
<syntaxhighlight lang="java">
    '''for''' X := 0.1 '''step''' 0.1 '''to''' 1.0 '''do'''
Collection<String> coll;
for (String s : coll) {}
</syntaxhighlight>


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.
Example in C#:


=== Condition-controlled loops ===
<syntaxhighlight lang="csharp">
{{main article|While loop|Do while loop}}
foreach (string s in myStringCollection) { xxx }
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.
</syntaxhighlight>


{| class="wikitable"
Example in PowerShell where 'foreach' is an alias of 'ForEach-Object':
|
DO 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.
<syntaxhighlight lang="powershell">
someCollection | foreach { $_ }
</syntaxhighlight>


    DO UNTIL (End-of-File)
Example in Fortran:
      IF new-zipcode <> current-zipcode
          display_tally(current-zipcode, zipcount)
         
          current-zipcode = new-zipcode
          zipcount = 0
      ENDIF
     
      zipcount++
    LOOP


=== Collection-controlled loops ===
<syntaxhighlight lang="fortran">
{{main article|Foreach loop|l1=Foreach}}
forall ( index = first:last:step... )
Several programming languages (e.g., [[Ada (programming language)|Ada]], [[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.
</syntaxhighlight>


    someCollection '''do''': [:eachElement |xxx].
    '''for''' Item '''in''' Collection '''do''' '''begin''' xxx '''end''';
    '''foreach''' (item; myCollection) { xxx }
    '''foreach''' someArray { xxx }
    '''foreach''' ($someArray as $k => $v) { xxx }
    Collection<String> coll; '''for''' (String s : coll) {}
    '''foreach''' ('''string''' s '''in''' myStringCollection) { xxx }
    someCollection | 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.
[[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 ===
====Infinite====
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.
{{excerpt |Infinite loop}}


=== Infinite loops ===
====Loop-and-a-half problem{{anchor |loop-and-a-half-problem}}====
{{main article|Infinite loop}}
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" />
[[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.
 
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'''


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>).
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}}


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.
====Unstructured====
A loop construct provides for structured completion criteria that either results in another iteration or continuing execution after the loop statement. But, various unstructured control flow constructs are supported by many languages.


=== Continuation with next iteration ===
; Early next iteration{{anchor |continue-statement}}: Some languages provide a construct that jumps control to the beginning of the loop body for the next iteration; for example, <code>continue</code> (most common), <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).
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 ===
; Redo 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 jumps to the start of the body for the same 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 ===
; Restart: Ruby has a <code>retry</code> statement that restarts the entire loop from the first 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>
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>


=== Early exit from loops ===
=====Early exit{{anchor |early-exit}}=====
When using a count-controlled loop to search through a table, it might be desirable to stop searching as soon as the required item is found. 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. Another term for early-exit loops is [[loop-and-a-half]].
Early exit jumps control to after the loop body <ref>Is a common way to solve the [[loop-and-a-half]] problem.</ref><ref name="roberts"/> For example, when searching a list, can stop looping when the item is found. Some programming languages provide a statement such as <code>break</code> (most languages), <code>Exit</code> (Visual Basic), or <code>last</code> (Perl).


The following example is done in [[Ada (programming language)|Ada]] which supports both ''early exit from loops'' and ''[[Control flow#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.
In the following Ada code, the loop exits when X is 0.


<syntaxhighlight lang="ada">
<syntaxhighlight lang="ada">
with Ada.Text IO;
loop
with Ada.Integer Text IO;
    Get(X);
    if X = 0 then
        exit;
    end if;
    DoSomething(X);
end loop;
</syntaxhighlight>
 
A more idiomatic style uses {{code |exit when}}:


procedure Print_Squares is
<syntaxhighlight lang="ada">
    X : Integer;
loop
begin
     Get(X);
     Read_Data : loop
     exit when X = 0;
        Ada.Integer Text IO.Get(X);
    DoSomething(X);
     exit Read_Data when X = 0;
end loop;
        Ada.Text IO.Put (X * X);
        Ada.Text IO.New_Line;
    end loop Read_Data;
end Print_Squares;
</syntaxhighlight>
</syntaxhighlight>


[[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,
[[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. In the following Python code, the <code>else</code> clause 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.


<syntaxhighlight lang="python">
<syntaxhighlight lang="python">
Line 382: Line 445:
</syntaxhighlight>
</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.
======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 Ada, Go, Java, Rust 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. Neither C nor C++ currently have multilevel break or named loops, 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> However, the inclusion of this feature has been proposed,<ref>{{Cite web|title=named-loops|url=https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3355.htm|website=open-std.org|date=18 September 2024}}</ref> and was added to C2Y.,<ref>{{Cite web|title=Information technology — Programming languages — C|url=https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3550.pdf|website=open-std.org|date=4 May 2025}}</ref> following the Java syntax. 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=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.
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>
 
=====Middle test=====
The following structure was proposed by [[Ole-Johan Dahl|Dahl]] in 1972:<ref>Dahl & Dijkstra & Hoare, "Structured Programming" Academic Press, 1972.</ref>
 
    '''loop'''                          '''loop'''
        xxx1                          read(char);
    '''while''' test;                    '''while''' '''not''' atEndOfFile;
        xxx2                          write(char);
    '''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'''.
 
This structure is not widely supported, with most languages instead using '''if''' ... '''break''' for conditional early exit.
 
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>
 
<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.


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>
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:


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.
<syntaxhighlight lang="c">
Theory of Computing, (May 1973), 240-252; also in J. Computer and System Sciences, 9,
while (statement_1, statement_2, condition) {
3 (December 1974). cited by {{cite journal
    statement_a;
|last=Knuth |first=Donald
    statement_b;
|author-link=Donald Knuth
}
|year=1974
</syntaxhighlight>
|title=Structured Programming with go to Statements
|journal=Computing Surveys
|volume=6
|issue=4
|pages=261–301
|doi=10.1145/356635.356640
|citeseerx=10.1.1.103.6084
|s2cid=207630080
}}</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"/>


One can also <code>return</code> out of a subroutine executing the looped statements, breaking out of both the nested loop and the subroutine. There are other [[#Proposed control structures|proposed control structures]] for multiple breaks, but these are generally implemented as exceptions instead.
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>


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>
<syntaxhighlight lang="c">
while (read_string(s), strlen(s) > 0) {
    // ...
}
</syntaxhighlight>


=== Loop variants and invariants ===
====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>
[[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>


Line 415: Line 514:
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]].
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 ===
====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.
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. -->
====Loop system cross-reference table====


{| class="wikitable"
{| class="wikitable"
|-
|-
! rowspan=2 |[[Programming language]]
! rowspan=2 | [[Programming language]]
! colspan=3 | conditional
! colspan=3 | Conditional
! colspan=4 | loop
! colspan=4 | Loop
! rowspan=2 | early exit
! rowspan=2 | Early exit
! rowspan=2 | loop continuation
! rowspan=2 | Loop continuation
! rowspan=2 | redo
! rowspan=2 | Redo
! rowspan=2 | retry
! rowspan=2 | Retry
! colspan=2 | correctness facilities
! colspan=2 | Correctness facilities
|-
|-
! begin
! Begin
! middle
! Middle
! end
! End
! count
! Numeric
! collection
! Collection
! general
! General
! infinite {{ref_label|loop_infinite|1|a}}
! Infinite {{ref_label|loop_infinite|1|a}}
! variant
! Variant
! invariant
! Invariant
|-
|-
| [[Ada (programming language)|Ada]]
| [[Ada (programming language)|Ada]]
Line 482: Line 581:
| {{partial|deep nested}} {{ref_label|deep_break_c|3|a}}
| {{partial|deep nested}} {{ref_label|deep_break_c|3|a}}
| {{no}}
| {{no}}
|
| {{no}}
|
| {{no}}
|
| {{no}}
|-  
|-  
| [[C++]]
| [[C++]]
Line 497: Line 596:
| {{partial|deep nested}} {{ref_label|deep_break_c|3|a}}
| {{partial|deep nested}} {{ref_label|deep_break_c|3|a}}
| {{no}}
| {{no}}
|
| {{no}}
|
| {{no}}
|
| {{no}}
|-
|-
| [[C Sharp (programming language)|C#]]
| [[C Sharp (programming language)|C#]]
Line 511: Line 610:
| {{partial|deep nested}} {{ref_label|deep_break_c|3|c}}
| {{partial|deep nested}} {{ref_label|deep_break_c|3|c}}
| {{partial|deep nested}} {{ref_label|deep_break_c|3|a}}
| {{partial|deep nested}} {{ref_label|deep_break_c|3|a}}
|
| {{no}}
|
| {{no}}
|
| {{no}}
|
| {{no}}
|-
|-
| [[COBOL]]
| [[COBOL]]
Line 678: Line 777:
| {{no}}
| {{no}}
|
|
|{{yes|non-native}} {{ref_label|requires_JML|12|a}}
| {{unofficial|non-native}} {{ref_label|requires_JML|12|a}}
|{{yes|non-native}} {{ref_label|requires_JML|12|a}}
| {{unofficial|non-native}} {{ref_label|requires_JML|12|a}}
|-
|-
| [[JavaScript]]
| [[JavaScript]]
Line 692: Line 791:
| {{yes|deep nested}}
| {{yes|deep nested}}
| {{no}}
| {{no}}
|
| {{no}}
|
| {{no}}
|-
| [[Kotlin (programming language)|Kotlin]]
| {{yes}}
| {{no}}
| {{yes}}
| {{maybe}}
| {{yes}}
| {{no}}
| {{no}}
| {{yes|deep nested}}
| {{yes|deep nested}}
| {{no}}
| {{no}}
| {{no}}
| {{no}}
|-
|-
| Natural
| Natural
Line 720: Line 834:
| {{no}}
| {{no}}
| {{no}}
| {{no}}
|
|
|
|-
| [[Odin (programming language)|Odin]]
| {{no}} {{ref_label|odin_general_loop|17|a}}
| {{no}}
| {{no}}
| {{no}} {{ref_label|loop_range|5|f}}
| {{partial|builtin only}}
| {{yes}}
| {{no}} {{ref_label|odin_general_loop|17|b}}
| {{yes|deep nested}}
| {{yes|deep nested}}
|
|
|
|
|
Line 735: Line 864:
| {{yes|deep nested}}
| {{yes|deep nested}}
| {{no}}
| {{no}}
|
| {{no}}
|
| {{no}}
|
| {{no}}
|-  
|-  
| [[Perl]]
| [[Perl]]
Line 765: Line 894:
| {{partial|deep nested}} {{ref_label|deep_break_e|6|c}}
| {{partial|deep nested}} {{ref_label|deep_break_e|6|c}}
| {{no}}
| {{no}}
|
| {{no}}
|
| {{no}}
|
| {{no}}
|-
|-
| [[Rebol]]
| [[Rebol]]
Line 798: Line 927:
|
|
|
|
|-
| [[Rust (programming language)|Rust]]
| {{yes}}
| {{no}}
| {{no}}
| {{no}} {{ref_label|loop_range|5|d}}
| {{yes}}
| {{no}}
| {{yes}}
| {{yes|deep nested}}
| {{yes|deep nested}}
| {{no}}
| {{no}}
| {{no}}
| {{no}}
|-
|-
| [[Standard ML]]
| [[Standard ML]]
Line 813: Line 957:
|
|
|
|
|-
| [[Swift (programming language)|Swift]]
| {{yes}}
| {{no}}
| {{yes}}
| {{no}}
| {{yes}}
| {{yes}}
| {{no}}
| {{yes|deep nested}}
| {{yes|deep nested}}
| {{no}}
| {{no}}
| {{no}}
| {{no}}
|-
|-
| [[Visual Basic .NET]]
| [[Visual Basic .NET]]
Line 824: Line 983:
| {{partial|one level per type of loop}}
| {{partial|one level per type of loop}}
| {{partial|one level per type of loop}}
| {{partial|one level per type of loop}}
|
| {{no}}
|
| {{no}}
|
| {{no}}
|
| {{no}}
|-  
|-  
| [[PowerShell]]
| [[PowerShell]]
Line 837: Line 996:
| {{yes}}
| {{yes}}
| {{no}}
| {{no}}
| {{dunno}}
| {{yes}}
| {{yes}}
|
| {{yes}}
|
| {{no}}
|
| {{no}}
|
| {{no}}
| {{no}}
|-
| [[Zig (programming language)|Zig]]
| {{yes}}
| {{no}}
| {{no}}
| {{no}} {{ref_label|loop_range|5|e}}
| {{partial|builtin only}}
| {{no}}
| {{no}}
| {{yes|deep nested}}
| {{yes|deep nested}}
| {{no}}
| {{no}}
| {{no}}
| {{no}}
|}
|}
# {{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_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.
Line 848: Line 1,022:
# {{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|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_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|loop_range|5|a}}{{note label|loop_range|5|b}}{{note label|loop_range|5|c}}{{note label|loop_range|5|d}}{{note label|loop_range|5|e}}{{note label|loop_range|5|f}} 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|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|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|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>[http://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|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|count_loop_eiffel|10|a}} Numeric 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|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|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]
# {{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|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|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.
# {{note_label|cl_sequence_type|14|a}} Common Lisp predates the concept of generic collection type.
# {{note_label|odin_general_loop|17|a}}{{note_label|odin_general_loop|17|b}} Odin's general <code>for</code> loop supports syntax shortcuts for conditional loop and infinite loop.


== Structured non-local control flow ==
===Non-local===
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.
Many programming languages, especially those favoring more dynamic styles of programming, offer constructs for non-local control flow which cause execution to jump from the current execution point to a [[predeclared]] point. Notable examples follow.


=== Conditions ===
====Condition handling====
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.
The earliest [[Fortran]] compilers supported statements for handling exceptional conditions including <code>IF ACCUMULATOR OVERFLOW</code>, <code>IF QUOTIENT OVERFLOW</code>, and <code>IF DIVIDE CHECK</code>. 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.
[[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.
Line 873: Line 1,048:
Unfortunately, some implementations had a substantial overhead in both space and time (especially SUBSCRIPTRANGE), so many programmers tried to avoid using conditions.
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:
A typical example of syntax:


  '''ON''' ''condition'' '''GOTO''' ''label''
'''ON''' ''condition'' '''GOTO''' ''label''


=== Exceptions ===
====Exception handling====
{{main article|Exception handling}}
Many modern languages support an [[exception handling]] construct that is structured; does not rely on jump semantics (goto). Generally, exceptional control flow starts with an exception object being thrown (a.k.a. raised). Control then proceeds to the inner-most exception handler for the [[call stack]]. If the handler handles the exception, then flow control reverts to normal. Otherwise, control proceeds outward to containing handlers until one handles the exception or the program reaches the outermost scope and exits. As control flows to progressively outer handlers, aspects that would normally occur such as popping the call stack are handled automatically.
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">
The following C++ code demonstrates structured exception handling. If an exception propagates from the execution of {{code |doSomething()}} and the exception object type matches one of the types specified in a catch clause, then that clause is executed. For example, if an exception of type {{code |SomeException}} is propagated by {{code |doSomething()}}, then control jumps from line 2 to 4 and the message "Caught SomeException" is printed and then control jumps to after the  {{code |try}} statement, line 8. If an exception of any other type is propagated, then control jumps from line 2 to 6. If no exception, then control jumps from 2 to 8.
 
<syntaxhighlight lang="cpp" line>
try {
try {
     xxx1                                  // Somewhere in here
     doSomething();
    xxx2                                  //    use: '''throw''' someValue;
} catch (const SomeException& e)
    xxx3
     std::println("Caught SomeException: {}", e.what());
} catch (someClass& someId) {            // catch value of someClass
} catch (...) {
     actionForSomeClass
     std::println("Unknown error");
} catch (someType& anotherId) {          // catch value of someType
    actionForSomeType
} catch (...) {                           // catch anything not already caught
     actionForAnythingElse
}
}
doNextThing();
</syntaxhighlight>
</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.
Many languages use the C++ keywords ({{code |throw}}, {{code |try}} and {{code |catch}}), but some languages use other keywords. For example, Ada uses {{code |exception}} to introduce an exception handler and {{code |when}} instead of {{code |catch}}. [[AppleScript]] incorporates placeholders in the syntax to extract information about the exception as shown in the following AppleScript code.<!-- should explain what the keywords ("from", "to", and "partial results") do.-->
 
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">
<syntaxhighlight lang = "applescript">
try
try
     set myNumber to myNumber / 0
     set myNumber to myNumber / 0
on error e number n from f to t partial result pr
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"
     if ( e = "Can't divide by zero" ) then display dialog "You must not do that"
end try
end try
</syntaxhighlight>
</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 many languages (including Object Pascal, D, Java, C#, and Python) a {{code| finally}} clause at the end of a {{code| try}} statement is executed at the end of the try statement; whether an exception propagates from the rest of the {{code| try}} or not. The following C# code ensures that the stream {{code|stream}} is closed.
 
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">
<syntaxhighlight lang="csharp">
FileStream stm = null;                   // C# example
FileStream stream = null;
try
try
{
{
     stm = new FileStream("logfile.txt", FileMode.Create);
     stream = new FileStream("logfile.txt", FileMode.Create);
     return ProcessStuff(stm);             // may throw an exception
     return ProcessStuff(stream);
}  
}  
finally
finally
{
{
     if (stm != null)
     if (stream != null)
         stm.Close();
    {
         stream.Close();
    }
}
}
</syntaxhighlight>
</syntaxhighlight>


Since this pattern is fairly common, C# has a special syntax:
Since this pattern is common, C# provides the {{code |using}} statement to ensure cleanup. In the following code, even if ProcessStuff() propagates an exception, the <code>stream</code> object is released. Python's <code>with</code> statement and Ruby's block argument to <code>File.open</code> are used to similar effect.


<syntaxhighlight lang="csharp">
<syntaxhighlight lang="csharp">
using (var stm = new FileStream("logfile.txt", FileMode.Create))
using (FileStream stream = new("logfile.txt", FileMode.Create))
{
{
     return ProcessStuff(stm); // may throw an exception
     return ProcessStuff(stream);
}
}
</syntaxhighlight>
</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.
====Continuation====
 
{{excerpt |Continuation}}
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}}
|-
| [[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: Python 3.10.2 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}}</ref><ref>{{cite web|url=https://docs.rs/corona/0.4.3/corona/|title=Corona - Rust}}</ref>
| {{yes}}<ref>{{cite web|url=https://rust-lang.github.io/async-book/|title=Getting Started - Asynchronous Programming in Rust}}</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 ==
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]].


[[Donald Knuth]]'s 1974 article "Structured Programming with go to Statements",<ref>Knuth, Donald E. "Structured Programming with go to Statements" [[ACM Computing Surveys]] 6(4):261-301, December 1974.</ref> identifies two situations which were not covered by the control structures listed above, and gave examples of control structures which could handle these situations. Despite their utility, these constructs have not yet found their way into mainstream programming languages.
====Generator====
{{excerpt |Generator (computer science)}}


=== Loop with test in the middle ===
====Coroutine====
The following was proposed by [[Ole-Johan Dahl|Dahl]] in 1972:<ref>Dahl & Dijkstra & Hoare, "Structured Programming" Academic Press, 1972.</ref>
{{excerpt |Coroutine}}


    '''loop'''                          '''loop'''
====COMEFROM====
        xxx1                          read(char);
{{excerpt |COMEFROM}}
    '''while''' test;                    '''while''' '''not''' atEndOfFile;
        xxx2                          write(char);
    '''repeat''';                        '''repeat''';
 
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. The construction here can be thought of as a '''do''' loop with the while check in the middle. Hence this single construction can replace several constructions in most programming languages.


Languages lacking this construct generally emulate it using an equivalent infinite-loop-with-break idiom:
====Event-based early exit from nested loop====
'''while''' (true) {
[[Zahn's construct]] was proposed in 1974,<ref>Zahn, C. T. [https://cds.cern.ch/record/414919/files/dd-74-6.pdf "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.
    xxx1
    '''if''' ('''not''' test)
        '''break'''
    xxx2
}
 
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.
 
In [[Ada (programming language)|Ada]], the above loop construct ('''loop'''-'''while'''-'''repeat''') can be represented using 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 the following section).
 
<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>
 
Naming a loop (like ''Read_Data'' in this example) is optional but permits leaving the outer loop of several nested loops.
 
=== Multiple 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> A modified version is presented here.
     '''exitwhen''' EventA '''or''' EventB '''or''' EventC;
     '''exitwhen''' EventA '''or''' EventB '''or''' EventC;
         xxx
         xxx
Line 1,187: Line 1,144:
     '''endexit''';
     '''endexit''';


== Security ==
==See also==
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>
 
== See also ==
{{div col}}
{{div col}}
* [[Branch (computer science)]]
* {{Annotated link |Control flow analysis}}
* [[Control flow analysis|Control-flow analysis]]
* {{Annotated link |Control-flow diagram}}
* [[Control-flow diagram]]
* {{Annotated link |Control-flow graph}}
* [[Control-flow graph]]
* {{Annotated link |Control table}}
* [[Control table]]
* {{Annotated link |Coroutine}}
* [[Coroutine]]
* {{Annotated link |Cyclomatic complexity}}
* [[Cyclomatic complexity]]
* {{Annotated link |DRAKON}}
* [[DRAKON|Drakon-chart]]
* {{Annotated link |Event loop}}
* [[Flowchart]]
* {{Annotated link |Flowchart}}
* [[Goto]]
* {{Annotated link |Jeroo}}
* [[Jeroo]], helps learn control structures
* {{Annotated link |Recursion}}
* [[Main loop]]
* {{Annotated link |Scheduling (computing)}}
* [[Recursion]]
* {{Annotated link |Spaghetti code}}
* [[Scheduling (computing)]]
* {{Annotated link |Switch statement}}
* [[Spaghetti code]]
* {{Annotated link |Zahn's construct}}
* [[Structured programming]]
* [[Subroutine]]
* [[Switch statement]], alters control flow conditionally
* [[Zahn's construct]]
{{div col end}}
{{div col end}}
== Notes ==
{{Notelist}}


== References ==
== References ==

Latest revision as of 06:40, 6 November 2025

Template:Short description Script error: No such module "Distinguish". Template:Loop constructs In software, control flow (or flow of control) describes how execution progresses from one command to the next. In many contexts, such as machine code and an imperative programming language, control progresses sequentially (to the command located immediately after the currently executing command) except when a command transfers control to another point Template:Endash in which case the command is classified as a control flow command. Depending on context, other terms are used instead of command. For example, in machine code, the typical term is instruction and in an imperative language, the typical term is statement.

Although an imperative language encodes control flow explicitly, languages of other programming paradigms are less focused on control flow. A declarative language specifies desired results without prescribing an order of operations. A functional language uses both language constructs and functions to control flow even though they are usually not called control flow statements.

For a central processing unit (CPU) instruction set, a control flow instruction often alters the program counter and is either an unconditional branch (a.k.a. jump) or a conditional branch. An alternative approach is predication which conditionally enables instructions instead of branching.

An asynchronous control flow transfer such as an interrupt or a signal alters the normal flow of control to a hander before returning control to where it was interrupted.

One way to attack software is to redirect the flow of execution. A variety of control-flow integrity techniques, including stack canaries, buffer overflow protection, shadow stacks, and vtable pointer verification, are used to defend against these attacks.[1][2][3]

Structure

Control flow is closely related to code structure. Control flows along lines defined by structure and the execution rules of a language. This general concept of structure is not be confused with structured programming which limits structure to sequencing, selection and iteration based on block organization.

Sequence

Sequential execution is the most basic structure. Although not all code is sequential in nature, imperative code is.

Label

A label identifies a position in source code. Some control flow statements reference a label so that control jumps to the labeled line. Other than marking a position, a label has no other effect.

Some languages limit a label to a number which is sometimes called a line number although that implies the inherent index of the line; not a label. None-the-less, such numeric labels are typically required to increment from top to bottom in a file even if not be sequential. For example, in BASIC:

10 LET X = 3
20 PRINT X
30 GOTO 10

In many languages, a label is an alphanumeric identifier, usually appearing at the start of a line and immediately followed by a colon. For example, the following C code defines a label Success on line 3 which identifies a jump target point at the first statement that follows it; line 4.

void f(bool ok) {
    if (ok) {
        goto success;
    }
    return;
success:
    printf("OK");
}

Block

Most languages provide for organizing sequences of code as a block. When used with a control statement, the beginning of a block provides a jump target. For example, in the following C code (which uses curly braces to delimit a block), control jumps from line 1 to 4 if done is false.

if (done) {
    printf("All done");
} else {
    printf("Still workin' on it");
}

ControlScript error: No such module "anchor".

Many control commands have been devised for programming languages. This section describes notable constructs; organized by functionality.

Function

A function provides for control flow in that when called, execution jumps to the start of the function's code and when it completes, control returns the calling point. In the following C code, control jumps from line 6 to 2 in order to call function foo(). Then, after completing the function body (printing "Hi"), control returns to after the call, line 7.

void foo() {
    printf("Hi");
}

void bar() {
    foo();
    printf("Done");
}

Branch

A branch command moves the point of execution from the point in the code that contains the command to the point that the command specifies.

Jump

A jump command unconditionally branches control to another point in the code, and is the most basic form of controlling the flow of code.

In a high-level language, this is often provided as a goto statement. Although the keyword may be upper or lower case or one or two words depending on the language, it is like: goto label. When control reaches a goto statement, control then jumps to the statement that follows the indicated label. The goto statement is been considered harmful by many computer scientists; notably Dijkstra.

Conditional branch

A conditional statement jumps control based on the value of a Boolean expression. Common variations include:

if-goto
Jumps to a label based on a condition; a high-level programming statement that closely mimics a similar used machine code instruction
if-then
Rather than being restricted to a jump, a statement or block is executed if the expression is true. In a language that does not include the then keyword, this can be called an if statement.
if-then-else
Like if-then, but with a second action to be performed if the condition is false. In a language that does not include the then keyword, this can be called an if-else statement.
Nested
Conditional statements are often nested inside other conditional statements.
Arithmetic if
Early Fortran, had an arithmetic if (a.k.a. three-way if) that tests whether a numeric value is negative, zero, or positive. This statement was deemed obsolete in Fortran-90, and deleted as of Fortran 2018.
Functional
Some languages have a functional form; for instance Lisp's cond.
Operator
Some languages have an operator form, such as the ternary conditional operator.
When and unless
Perl supplements a C-style if with when and unless.
Messages
Smalltalk uses ifTrue and ifFalse messages to implement conditionals, rather than a language construct.

The following Pascal code shows a simple if-then-else. The syntax is similar in Ada:

if a > 0 then
  writeln("yes")
else
  writeln("no");

In C:

if (a > 0) { 
    puts("yes");
} else {
    puts("no");
}

In bash:

if [ $a -gt 0 ]; then
      echo "yes"
else
      echo "no"
fi

In Python:

if a > 0: 
    print("yes")
else:
    print("no")

In Lisp:

(princ
  (if (plusp a)
      "yes"
      "no"))

Multiway branch

A multiway branch jumps control based on matching values. There is usually a provision for a default action if no match is found. A switch statement can allow compiler optimizations, such as lookup tables. In dynamic languages, 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 *) implements the default case as a glob matching any string. Case logic can also be implemented in functional form, as in SQL's decode statement.

The following Pascal code shows a relatively simple switch statement. Pascal uses the case keyword instead of switch.

case someChar of
  'a': actionOnA;
  'x': actionOnX;
  'y','z':actionOnYandZ;
  else actionOnNoMatch;
end;

In Ada:

case someChar is
  when 'a' => actionOnA;
  when 'x' => actionOnX;
  when 'y' | 'z' => actionOnYandZ;
  when others => actionOnNoMatch;
end;

In C:

switch (someChar) {
    case 'a': 
        actionOnA; 
        break;
    case 'x': 
        actionOnX; 
        break;
    case 'y':
    case 'z': 
        actionOnYandZ;
        break;
    default: 
        actionOnNoMatch;
}

In Bash:

case $someChar in 
   a)    actionOnA ;;
   x)    actionOnX ;;
   [yz]) actionOnYandZ ;;
   *)    actionOnNoMatch  ;;
esac

In Lisp:

(case some-char
  ((#\a)     action-on-a)
  ((#\x)     action-on-x)
  ((#\y #\z) action-on-y-and-z)
  (else      action-on-no-match))

In Fortran:

select case (someChar)
  case ('a')
    actionOnA
  case ('x')
    actionOnX
  case ('y','z')
    actionOnYandZ
  case default
    actionOnNoMatch
end select

LoopScript error: No such module "anchor".

File:Programmingloops.svg
basic types of program loops

A loop is a sequence of statements, loop body, which is executed a number of times based on runtime state. The body is executed once for each item of a collection (definite iteration), until a condition is met (indefinite iteration), or infinitely. A loop inside the loop body is called a nested loop.[4][5][6] Early exit from a loop may be supported via a break statement.[7][8]

In a functional programming language, such as Haskell and Scheme, both recursive and iterative processes are expressed with tail recursive procedures instead of looping constructs that are syntactic.

Numeric

Script error: No such module "Labelled list hatnote". A relatively simple yet useful loop iterates over a range of numeric values. A simple form starts at an integer value, ends at a larger integer value and iterates for each integer value between. Often, the increment can be any integer value; even negative to loop from a larger to a smaller value.

Example in BASIC:

FOR I = 1 TO N
   xxx
NEXT I

Example in Pascal:

for I := 1 to N do begin
   xxx
end;

Example in Fortran:

DO I = 1,N
    xxx
END DO

In many programming languages, only integers can be used at all or reliably. As a floating-point number is represented imprecisely due to hardware constraints, the following loop might iterate 9 or 10 times, depending on various factors such as rounding error, hardware, compiler. 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 commonly expected sequence of 0.1, 0.2, 0.3, ..., 1.0.

for X := 0.1 step 0.1 to 1.0 do

Condition-controlled

Script error: No such module "Labelled list hatnote". Some loop constructs iterate until a condition is true. Some variations test the condition at the start of the loop; others test at the end. If the test is at the start, the body may be skipped completely. At the end, the body is always executed at least once.

Example in Visual Basic:

DO WHILE (test)
    xxx
LOOP

Example in Pascal:

repeat
    xxx
until test;

Example in C family of pre-test:

while (test) {
    xxx
}

Example in C family of post-test:

do
    xxx
while (test);

Although using the for keyword, the 3-part, c-style loop is condition-based; not a numeric-based construct. The condition, 2nd part, is evaluated before each loop so the loop is pre-test. The 1st part is a place to initialize state and the 3rd part is for incrementing for the next iteration, but both aspects can be performed elsewhere. The following C code implements the logic of a numeric loop that iterates for i from 0 to n-1.

for (int i = 0; i < n; ++i) {
    xxx
}

Enumeration

Script error: No such module "Labelled list hatnote". Some loop constructs enumerate the items of a collection; iterating for each item.

Example in Smalltalk:

someCollection do: [:eachElement |xxx].

Example in Pascal:

for Item in Collection do begin xxx end;

Example in Raku:

foreach (item; myCollection) { xxx }

Example in TCL:

foreach someArray { xxx }

Example in PHP:

foreach ($someArray as $k => $v) { xxx }

Example in Java:

Collection<String> coll; 
for (String s : coll) {}

Example in C#:

foreach (string s in myStringCollection) { xxx }

Example in PowerShell where 'foreach' is an alias of 'ForEach-Object':

someCollection | foreach { $_ }

Example in Fortran:

forall ( index = first:last:step... )

Scala has 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.

Infinite

Template:Excerpt

Loop-and-a-half problemScript error: No such module "anchor".

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.[9] Other than the traditional unstructured solution of a goto statement,Template:Sfn 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).[9]

A common case is where the start of the loop is always executed, but the end may be skipped on the last iteration.Template:Sfn This was dubbed by Dijkstra a loop which is performed "n and a half times",[10] and is now called the loop-and-a-half problem.[8] 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.Template:Sfn[8] In these cases, the first part of the loop is executed Template:Tmath times, but the second part is only executed Template:Tmath times.

This problem has been recognized at least since 1967 by Knuth, with Wirth suggesting solving it via early loop exit.Template:Sfn Since the 1990s this has been the most commonly taught solution, using a break statement, as in:[8]

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 control structure explicitly supports the loop-an-a-half use case, without reversing the condition.Template:Sfn

Unstructured

A loop construct provides for structured completion criteria that either results in another iteration or continuing execution after the loop statement. But, various unstructured control flow constructs are supported by many languages.

Early next iterationScript error: No such module "anchor".
Some languages provide a construct that jumps control to the beginning of the loop body for the next iteration; for example, continue (most common), skip,[11] cycle (Fortran), or next (Perl and Ruby).
Redo iteration
Some languages, like Perl[12] and Ruby,[13] have a redo statement that jumps to the start of the body for the same iteration.
Restart
Ruby has a retry statement that restarts the entire loop from the first iteration.[14]
Early exitScript error: No such module "anchor".

Early exit jumps control to after the loop body [15][8] For example, when searching a list, can stop looping when the item is found. Some programming languages provide a statement such as break (most languages), Exit (Visual Basic), or last (Perl).

In the following Ada code, the loop exits when X is 0.

loop
    Get(X);
    if X = 0 then
        exit;
    end if;
    DoSomething(X);
end loop;

A more idiomatic style uses exit when:

loop
    Get(X);
    exit when X = 0;
    DoSomething(X);
end loop;

Python supports conditional execution of code depending on whether a loop was exited early (with a break statement) or not by using an else-clause with the loop. In the following Python code, the else clause is linked to the for statement, and not the inner if statement. Both Python's for and while loops support such an else clause, which is executed only if early exit of the loop has not occurred.

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")
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[16] and PHP,[17] or via labeled breaks (break out and continue at given label), as in Ada, Go, Java, Rust and Perl.[18] 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. Neither C nor C++ currently have multilevel break or named loops, and the usual alternative is to use a goto to implement a labeled break.[19] However, the inclusion of this feature has been proposed,[20] and was added to C2Y.,[21] following the Java syntax. Python does not have a multilevel break or continue – this was proposed in PEP 3136, and rejected on the basis that the added complexity was not worth the rare legitimate use.[22]

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.[23] 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.[24] 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.[23]

In his 2004 textbook, David Watt uses Tennent's notion of 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.[25]

Middle test

The following structure was proposed by Dahl in 1972:[26]

   loop                           loop
       xxx1                           read(char);
   while test;                    while not atEndOfFile;
       xxx2                           write(char);
   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 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),Template:Sfn functioning as until instead of while.

This structure is not widely supported, with most languages instead using if ... break for conditional early exit.

This is supported by some languages, such as Forth, where the syntax is BEGIN ... WHILE ... REPEAT,[27] and the shell script languages Bourne shell (sh) and bash, where the syntax is while ... do ... done or until ... do ... done, as:[28][29]

while
  statement-1
  statement-2
  ...
  condition
do
  statement-a
  statement-b
  ...
done

The shell syntax works because the while (or until) loop accepts a list of commands as a condition,[30] 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 other languages with similar constructs, which allow shoehorning a list of statements into the while condition:

while (statement_1, statement_2, condition) {
    statement_a;
    statement_b;
}

While legal, this is marginal, and it is primarily used, if at all, only for short modify-then-test cases, as in:[31]

while (read_string(s), strlen(s) > 0) {
    // ...
}

Loop variants and invariants

Loop variants and loop invariants are used to express correctness of loops.[32]

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 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 loop statements in Java.

Loop sublanguage

Some Lisp dialects provide an extensive sublanguage for describing Loops. An early example can be found in Conversional Lisp of Interlisp. Common Lisp[33] provides a Loop macro which implements such a sublanguage.

Loop system cross-reference table

Programming language Conditional Loop Early exit Loop continuation Redo Retry Correctness facilities
Begin Middle End Numeric Collection General Infinite <templatestyles src="Citation/styles.css"/>[1] Variant Invariant
Ada Yes Yes Yes Yes arrays No Yes deep nested No
APL Yes No Yes Yes Yes Yes Yes deep nested <templatestyles src="Citation/styles.css"/>[3] Yes No No
C Yes No Yes No <templatestyles src="Citation/styles.css"/>[2] No Yes No deep nested <templatestyles src="Citation/styles.css"/>[3] deep nested <templatestyles src="Citation/styles.css"/>[3] No No No No
C++ Yes No Yes No <templatestyles src="Citation/styles.css"/>[2] Yes <templatestyles src="Citation/styles.css"/>[9] Yes No deep nested <templatestyles src="Citation/styles.css"/>[3] deep nested <templatestyles src="Citation/styles.css"/>[3] No No No No
C# Yes No Yes No <templatestyles src="Citation/styles.css"/>[2] Yes Yes No deep nested <templatestyles src="Citation/styles.css"/>[3] deep nested <templatestyles src="Citation/styles.css"/>[3] No No No No
COBOL Yes No Yes Yes No Yes No deep nested <templatestyles src="Citation/styles.css"/>[15] deep nested <templatestyles src="Citation/styles.css"/>[14] No
Common Lisp Yes Yes Yes Yes builtin only <templatestyles src="Citation/styles.css"/>[16] Yes Yes deep nested No
D Yes No Yes Yes Yes Yes Yes<templatestyles src="Citation/styles.css"/>[14] deep nested deep nested No
Eiffel Yes No No Yes <templatestyles src="Citation/styles.css"/>[10] Yes Yes No one level <templatestyles src="Citation/styles.css"/>[10] No No No <templatestyles src="Citation/styles.css"/>[11] integer only <templatestyles src="Citation/styles.css"/>[13] Yes
F# Yes No No Yes Yes No No No <templatestyles src="Citation/styles.css"/>[6] No No
FORTRAN 77 Yes No No Yes No No No one level Yes No No
Fortran 90 Yes No No Yes No No Yes deep nested deep nested No No
Fortran 95 and later Yes No No Yes arrays No Yes deep nested deep nested No No
Go Yes No No Yes builtin only Yes Yes deep nested deep nested No
Haskell No No No No Yes No Yes No <templatestyles src="Citation/styles.css"/>[6] No No
Java Yes No Yes No <templatestyles src="Citation/styles.css"/>[2] Yes Yes No deep nested deep nested No Template:Unofficial <templatestyles src="Citation/styles.css"/>[12] Template:Unofficial <templatestyles src="Citation/styles.css"/>[12]
JavaScript Yes No Yes No <templatestyles src="Citation/styles.css"/>[2] Yes Yes No deep nested deep nested No No No
Kotlin Yes No Yes Template:Maybe Yes No No deep nested deep nested No No No No
Natural Yes Yes Yes Yes No Yes Yes Yes Yes Yes No
OCaml Yes No No Yes arrays,lists No No No <templatestyles src="Citation/styles.css"/>[6] No No
Odin No <templatestyles src="Citation/styles.css"/>[17] No No No <templatestyles src="Citation/styles.css"/>[5] builtin only Yes No <templatestyles src="Citation/styles.css"/>[17] deep nested deep nested
PHP Yes No Yes No <templatestyles src="Citation/styles.css"/>[2] <templatestyles src="Citation/styles.css"/>[5] Yes <templatestyles src="Citation/styles.css"/>[4] Yes No deep nested deep nested No No No No
Perl Yes No Yes No <templatestyles src="Citation/styles.css"/>[2] <templatestyles src="Citation/styles.css"/>[5] Yes Yes No deep nested deep nested Yes
Python Yes No No No <templatestyles src="Citation/styles.css"/>[5] Yes No No deep nested <templatestyles src="Citation/styles.css"/>[6] deep nested <templatestyles src="Citation/styles.css"/>[6] No No No No
Rebol No <templatestyles src="Citation/styles.css"/>[7] Yes Yes Yes Yes No <templatestyles src="Citation/styles.css"/>[8] Yes one level <templatestyles src="Citation/styles.css"/>[6] No No
Ruby Yes No Yes Yes Yes No Yes deep nested <templatestyles src="Citation/styles.css"/>[6] deep nested <templatestyles src="Citation/styles.css"/>[6] Yes Yes
Rust Yes No No No <templatestyles src="Citation/styles.css"/>[5] Yes No Yes deep nested deep nested No No No No
Standard ML Yes No No No arrays,lists No No No <templatestyles src="Citation/styles.css"/>[6] No No
Swift Yes No Yes No Yes Yes No deep nested deep nested No No No No
Visual Basic .NET Yes No Yes Yes Yes No Yes one level per type of loop one level per type of loop No No No No
PowerShell Yes No Yes No <templatestyles src="Citation/styles.css"/>[2] Yes Yes No Yes Yes No No No No
Zig Yes No No No <templatestyles src="Citation/styles.css"/>[5] builtin only No No deep nested deep nested No No No No
  1. <templatestyles src="Citation/styles.css"/>a while (true) does not count as an infinite loop for this purpose, because it is not a dedicated language structure.
  2. <templatestyles src="Citation/styles.css"/>a <templatestyles src="Citation/styles.css"/>b <templatestyles src="Citation/styles.css"/>c <templatestyles src="Citation/styles.css"/>d <templatestyles src="Citation/styles.css"/>e <templatestyles src="Citation/styles.css"/>f <templatestyles src="Citation/styles.css"/>g <templatestyles src="Citation/styles.css"/>h C's for (init; test; increment) loop is a general loop construct, not specifically a counting one, although it is often used for that.
  3. <templatestyles src="Citation/styles.css"/>a <templatestyles src="Citation/styles.css"/>b <templatestyles src="Citation/styles.css"/>c Deep breaks may be accomplished in APL, C, C++ and C# through the use of labels and gotos.
  4. <templatestyles src="Citation/styles.css"/>a Iteration over objects was added in PHP 5.
  5. <templatestyles src="Citation/styles.css"/>a <templatestyles src="Citation/styles.css"/>b <templatestyles src="Citation/styles.css"/>c <templatestyles src="Citation/styles.css"/>d <templatestyles src="Citation/styles.css"/>e <templatestyles src="Citation/styles.css"/>f A counting loop can be simulated by iterating over an incrementing list or generator, for instance, Python's range().
  6. <templatestyles src="Citation/styles.css"/>a <templatestyles src="Citation/styles.css"/>b <templatestyles src="Citation/styles.css"/>c <templatestyles src="Citation/styles.css"/>d <templatestyles src="Citation/styles.css"/>e Deep breaks may be accomplished through the use of exception handling.
  7. <templatestyles src="Citation/styles.css"/>a There is no special construct, since the while function can be used for this.
  8. <templatestyles src="Citation/styles.css"/>a There is no special construct, but users can define general loop functions.
  9. <templatestyles src="Citation/styles.css"/>a The C++11 standard introduced the range-based for. In the STL, there is a std::for_each template function which can iterate on STL containers and call a unary function for each element.[34] The functionality also can be constructed as macro on these containers.[35]
  10. <templatestyles src="Citation/styles.css"/>a Numeric looping is effected by iteration across an integer interval; early exit by including an additional condition for exit.
  11. <templatestyles src="Citation/styles.css"/>a Eiffel supports a reserved word retry, however it is used in exception handling, not loop control.
  12. <templatestyles src="Citation/styles.css"/>a Requires Java Modeling Language (JML) behavioral interface specification language.
  13. <templatestyles src="Citation/styles.css"/>a Requires loop variants to be integers; transfinite variants are not supported. Eiffel: Why loop variants are integers
  14. <templatestyles src="Citation/styles.css"/>a D supports infinite collections, and the ability to iterate over those collections. This does not require any special construct.
  15. <templatestyles src="Citation/styles.css"/>a Deep breaks can be achieved using GO TO and procedures.
  16. <templatestyles src="Citation/styles.css"/>a Common Lisp predates the concept of generic collection type.
  17. <templatestyles src="Citation/styles.css"/>a <templatestyles src="Citation/styles.css"/>b Odin's general for loop supports syntax shortcuts for conditional loop and infinite loop.

Non-local

Many programming languages, especially those favoring more dynamic styles of programming, offer constructs for non-local control flow which cause execution to jump from the current execution point to a predeclared point. Notable examples follow.

Condition handling

The earliest Fortran compilers supported statements for handling exceptional conditions including IF ACCUMULATOR OVERFLOW, IF QUOTIENT OVERFLOW, and IF DIVIDE CHECK. 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 IEEE_EXCEPTIONS 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.

A typical example of syntax:

ON condition GOTO label

Exception handling

Many modern languages support an exception handling construct that is structured; does not rely on jump semantics (goto). Generally, exceptional control flow starts with an exception object being thrown (a.k.a. raised). Control then proceeds to the inner-most exception handler for the call stack. If the handler handles the exception, then flow control reverts to normal. Otherwise, control proceeds outward to containing handlers until one handles the exception or the program reaches the outermost scope and exits. As control flows to progressively outer handlers, aspects that would normally occur such as popping the call stack are handled automatically.

The following C++ code demonstrates structured exception handling. If an exception propagates from the execution of doSomething() and the exception object type matches one of the types specified in a catch clause, then that clause is executed. For example, if an exception of type SomeException is propagated by doSomething(), then control jumps from line 2 to 4 and the message "Caught SomeException" is printed and then control jumps to after the try statement, line 8. If an exception of any other type is propagated, then control jumps from line 2 to 6. If no exception, then control jumps from 2 to 8.

try {
    doSomething();
} catch (const SomeException& e)
    std::println("Caught SomeException: {}", e.what());
} catch (...) {
    std::println("Unknown error");
}
doNextThing();

Many languages use the C++ keywords (throw, try and catch), but some languages use other keywords. For example, Ada uses exception to introduce an exception handler and when instead of catch. AppleScript incorporates placeholders in the syntax to extract information about the exception as shown in the following AppleScript code.

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

In many languages (including Object Pascal, D, Java, C#, and Python) a finally clause at the end of a try statement is executed at the end of the try statement; whether an exception propagates from the rest of the try or not. The following C# code ensures that the stream stream is closed.

FileStream stream = null;
try
{
    stream = new FileStream("logfile.txt", FileMode.Create);
    return ProcessStuff(stream);
} 
finally
{
    if (stream != null)
    {
        stream.Close();
    }
}

Since this pattern is common, C# provides the using statement to ensure cleanup. In the following code, even if ProcessStuff() propagates an exception, the stream object is released. Python's with statement and Ruby's block argument to File.open are used to similar effect.

using (FileStream stream = new("logfile.txt", FileMode.Create))
{
    return ProcessStuff(stream);
}

Continuation

Template:Excerpt

Generator

Template:Excerpt

Coroutine

Template:Excerpt

COMEFROM

Template:Excerpt

Event-based early exit from nested loop

Zahn's construct was proposed in 1974,[36] and discussed in Template:Harvtxt. A modified version is presented here.

   exitwhen EventA or EventB or EventC;
       xxx
   exits
       EventA: actionA
       EventB: actionB
       EventC: actionC
   endexit;

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 Template:Not a typo. 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 exception handling, and exceptions or similar constructs are used for this purpose in many languages.

The following simple example involves searching a two-dimensional table for a particular item.

   exitwhen found or missing;
       for I := 1 to N do
           for J := 1 to M do
               if table[I,J] = target then found;
       missing;
   exits
       found:   print ("item is in table");
       missing: print ("item is not in table");
   endexit;

See also

Template:Div col

Template:Div col end

References

Template: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

Template:Sister project Template:Sister project

  1. Script error: No such module "citation/CS1".
  2. Script error: No such module "citation/CS1".
  3. Script error: No such module "citation/CS1".
  4. Script error: No such module "citation/CS1".
  5. Script error: No such module "citation/CS1".
  6. Script error: No such module "citation/CS1".
  7. Script error: No such module "Citation/CS1".
  8. a b c d e Roberts, E. [1995] "Loop Exits and Structured Programming: Reopening the Debate Template:Webarchive," ACM SIGCSE Bulletin, (27)1: 268–272.
  9. a b Script error: No such module "citation/CS1".
  10. Edsger W. Dijkstra, personal communication to Donald Knuth on 1974-01-03, cited in Template:Harvtxt
  11. Script error: No such module "citation/CS1".
  12. Script error: No such module "citation/CS1".
  13. Script error: No such module "citation/CS1".
  14. Script error: No such module "citation/CS1".
  15. Is a common way to solve the loop-and-a-half problem.
  16. Advanced Bash Scripting Guide: 11.3. Loop Control
  17. PHP Manual: "break"
  18. perldoc: last
  19. comp.lang.c FAQ list · "Question 20.20b"
  20. Script error: No such module "citation/CS1".
  21. Script error: No such module "citation/CS1".
  22. [Python-3000] Announcing PEP 3136, Guido van Rossum
  23. a b Script error: No such module "citation/CS1".
  24. Kosaraju, S. Rao. "Analysis of structured programs," Proc. Fifth Annual ACM Syrup. Theory of Computing, (May 1973), 240-252; also in J. Computer and System Sciences, 9, 3 (December 1974), cited by Template:Harvtxt.
  25. Script error: No such module "citation/CS1".
  26. Dahl & Dijkstra & Hoare, "Structured Programming" Academic Press, 1972.
  27. Script error: No such module "citation/CS1".
  28. Script error: No such module "citation/CS1".
  29. Script error: No such module "citation/CS1".
  30. Script error: No such module "citation/CS1".
  31. Script error: No such module "citation/CS1".
  32. Script error: No such module "citation/CS1".
  33. Script error: No such module "citation/CS1".
  34. for_each. Sgi.com. Retrieved on 2010-11-09.
  35. Chapter 1. Boost.Foreach Template:Webarchive. Boost-sandbox.sourceforge.net (2009-12-19). Retrieved on 2010-11-09.
  36. Zahn, C. T. "A control statement for natural top-down structured programming" presented at Symposium on Programming Languages, Paris, 1974.