Jump to content

Control flow

From Wikipedia, the free encyclopedia

Incomputer science,control flow(orflow of control) is the order in which individualstatements,instructionsorfunction callsof animperativeprogramareexecutedor evaluated. The emphasis on explicit control flow distinguishes animperative programminglanguage from adeclarative programminglanguage.

Within an imperativeprogramming language,acontrol flow statementis a statement that results in a choice being made as to which of two or more paths to follow. Fornon-strictfunctional languages, functions andlanguage constructsexist to achieve the same result, but they are usually not termed control flow statements.

A set of statements is in turn generally structured as ablock,which in addition to grouping, also defines alexical scope.

Interruptsandsignalsare low-level mechanisms that can alter the flow of control in a way similar to asubroutine,but usually occur as a response to some external stimulus or event (that can occurasynchronously), rather than execution of anin-linecontrol flow statement.

At the level ofmachine languageorassembly language,control flow instructions usually work by altering theprogram counter.For somecentral processing units(CPUs), the only control flow instructions available are conditional or unconditionalbranchinstructions, also termed jumps.

Categories

[edit]
Astate diagramof a peptide ion mass mapping search process.

The kinds of control flow statements supported by different languages vary, but can be categorized by their effect:

  • Continuation at a different statement (unconditionalbranchor 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 asconditional branch)
  • Executing a set of distant statements, after which the flow of control usually returns (subroutines,coroutines,andcontinuations)
  • Stopping the program, preventing any further execution (unconditional halt)

Primitives

[edit]

Labels

[edit]

Alabelis an explicit name or number assigned to a fixed position within thesource 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 numbersare an alternative to a named label used in some languages (such asBASIC). They arewhole numbersplaced 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:

10LETX=3
20PRINTX

In other languages such asCandAda,a label is anidentifier,usually appearing at the start of a line and immediately followed by a colon. For example, in C:

Success:printf("The operation was successful.\n");

The languageALGOL 60allowed both whole numbers and identifiers as labels (both linked by colons to the following statement), but few if any otherALGOLvariants allowed whole numbers. EarlyFortrancompilers only allowed whole numbers as labels. Beginning with Fortran-90, Alpha numeric labels have also been allowed.

Goto

[edit]

Thegotostatement (a combination of the English wordsgoandto,and pronounced accordingly) is the most basic form of unconditional transfer of control.

Although thekeywordmay either be in upper or lower case depending on the language, it is usually written as:

gotolabel

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.

Goto statements have beenconsidered harmfulby many computer scientists, notablyDijkstra.

Subroutines

[edit]

The terminology forsubroutinesvaries; they may alternatively be known as routines, procedures, functions (especially if they return results) or methods (especially if they belong toclassesortype classes).

In the 1950s, computer memories were very small by current standards so subroutines were used mainlyhttps:// researchgate.net/publication/225114059_The_Bohm-Jacopini_Theorem_Is_False_Propositionallyto reduce program size. A piece of code was written once and then used many times from various other places in a program.

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 ofmodularitythat can help divide the work.

Sequence

[edit]

In structured programming, the ordered sequencing of successive commands is considered one of the basic control structures, which is used as a building block for programs alongside iteration, recursion and choice.

Minimal structured control flow

[edit]

In May 1966, Böhm and Jacopini published an article[1]inCommunications of the ACMwhich showed that any program withgotos 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; after all, computers theoretically need onlyone 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.

What Böhm and Jacopini's article showed was that all programs could be goto-free. Other research showed that control structures with one entry and one exit were much easier to understand than any other form,[citation needed]mainly because they could be used anywhere as a statement without disrupting the control flow. In other words, they werecomposable.(Later developments, such asnon-strict programming languages– and more recently, composablesoftware transactions– have continued this strategy, making components of programs even more freely composable.)

Some academics took a purist approach to the Böhm–Jacopini result and argued that even instructions likebreakandreturnfrom 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 languagePascal(designed in 1968–1969), which up to the mid-1990s was the preferred tool for teaching introductory programming in academia.[2]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 somecode duplication.[3]Pascal is affected by both of these problems and according to empirical studies cited byEric 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.[2]

Control structures in practice

[edit]

Most programming languages with control structures have an initial keyword which indicates the type of control structure involved.[clarification needed]Languages then divide as to whether or not control structures have a final keyword.

  • No final keyword:ALGOL 60,C,C++,Go,Haskell,Java,Pascal,Perl,PHP,PL/I,Python,PowerShell.Such languages need some way of grouping statements together:
    • ALGOL 60 and Pascal:begin...end
    • C, C++, Go, Java, Perl, PHP, and PowerShell:curly brackets{...}
    • PL/I:DO...END
    • Python: usesindentlevel (seeOff-side rule)
    • Haskell: eitherindentlevel or curly brackets can be used, and they can be freely mixed
    • Lua: usesdo...end
  • Final keyword:Ada,APL,ALGOL 68,Modula-2,Fortran 77,Mythryl,Visual Basic.The forms of the final keyword vary:
    • Ada: final keyword isend+space+ initial keyword e.g.,if...end if,loop...end loop
    • APL: final keyword is:Endoptionally + initial keyword, e.g.,:If...:Endor:If...:EndIf,Select...:Endor:Select...:EndSelect,however, if adding an end condition, the end keyword becomes:Until
    • ALGOL 68, Mythryl: initial keyword spelled backwards e.g.,if...fi,case...esac
    • Fortran 77: final keyword isEND+ initial keyword e.g.,IF...ENDIF,DO...ENDDO
    • Modula-2: same final keywordENDfor everything
    • Visual Basic: every control structure has its own keyword.If...End If;For...Next;Do...Loop;While...Wend

Choice

[edit]

If-then-(else) statements

[edit]

Conditional expressions and conditional constructs are features of aprogramming languagewhich perform different computations or actions depending on whether a programmer-specifiedbooleanconditionevaluates to true or false.

  • IF..GOTO.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.
  • IF..THEN..(ENDIF).Rather than being restricted to a jump, any simple statement, or nested block, could follow the THEN key keyword. This a structured form.
  • IF..THEN..ELSE..(ENDIF).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 terminalENDIF,others do not.Cand 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 allowELSEandIFto be combined intoELSEIF,avoiding the need to have a series ofENDIFor other final statements at the end of a compound statement.
Pascal: Ada:
ifa>0then
writeln("yes")
else
writeln("no");
ifa>0then
Put_Line("yes");
else
Put_Line("no");
endif;
C: Shell script:
if(a>0){
puts("yes");
}
else{
puts("no");
}
if[$a-gt0];then
echo"yes"
else
echo"no"
fi
Python: Lisp:
ifa>0:
print("yes")
else:
print("no")
(princ
(if(pluspa)
"yes"
"no"))

Less common variations include:

  • Some languages, such asFortran,have athree-wayorarithmetic if,testing whether a numeric value is positive, negative or zero.
  • Some languages have afunctionalform of anifstatement, for instanceLisp'scond.
  • Some languages have anoperatorform of anifstatement, such as C'sternary operator.
  • Perlsupplements a C-styleifwithwhenandunless.
  • SmalltalkusesifTrueandifFalsemessages to implement conditionals, rather than any fundamental language construct.

Case and switch statements

[edit]

Switch statements(orcase statements,ormultiway 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 aslookup tables.Indynamic languages,the cases may not be limited to constant expressions, and might extend topattern matching,as in theshell scriptexample on the right, where the*)implements the default case as aglobmatching any string. Case logic can also be implemented in functional form, as inSQL'sdecodestatement.

Pascal: Ada:
casesomeCharof
'a':actionOnA;
'x':actionOnX;
'y','z':actionOnYandZ;
elseactionOnNoMatch;
end;
casesomeCharis
when'a'=>actionOnA;
when'x'=>actionOnX;
when'y'|'z'=>actionOnYandZ;
whenothers=>actionOnNoMatch;
end;
C: Shell script:
switch(someChar){
case'a':actionOnA;break;
case'x':actionOnX;break;
case'y':
case'z':actionOnYandZ;break;
default:actionOnNoMatch;
}
case$someCharin
a)actionOnA;;
x)actionOnX;;
[yz])actionOnYandZ;;
*)actionOnNoMatch;;
esac
Lisp: Fortran:
(casesome-char
((#\a)action-on-a)
((#\x)action-on-x)
((#\y#\z)action-on-y-and-z)
(elseaction-on-no-match))
select case(someChar)
case('a')
actionOnA
case('x')
actionOnX
case('y','z')
actionOnYandZ
casedefault
actionOnNoMatch
end select

Loops

[edit]

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 (thebodyof the loop, shown below asxxx) is obeyed a specified number of times, or once for each of a collection of items, or until some condition is met, orindefinitely.When one of those items is itself also a loop, it is called a "nested loop".[4][5][6]

Infunctional programminglanguages, such asHaskellandScheme,bothrecursiveanditerativeprocesses are expressed withtail recursiveprocedures instead of looping constructs that are syntactic.

Count-controlled loops

[edit]

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.

FOR I = 1 TO N
xxx
NEXT I
forI:= 1toNdobegin
xxx
end;
DO I = 1,N
xxx
END DO
for( I=1; I<=N; ++I ) {
xxx
}

In these examples, if N < 1 then the body of loop may execute once (with I having value 1) or not at all, depending on the programming language.

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

forX:= 0.1step0.1to1.0do

might be repeated 9 or 10 times, depending on rounding errors and/or the hardware and/or the compiler version. Furthermore, if the increment of X occurs by repeated addition, accumulated rounding errors may mean that the value of X in each iteration can differ quite significantly from the expected sequence 0.1, 0.2, 0.3,..., 1.0.

Condition-controlled loops

[edit]

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.

DO WHILE (test)
xxx
LOOP
repeat
xxx
untiltest;
while(test) {
xxx
}
do
xxx
while(test);

Acontrol breakis 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.

DO UNTIL (End-of-File)
IF new-zipcode <> current-zipcode
display_tally(current-zipcode, zipcount)

current-zipcode = new-zipcode
zipcount = 0
ENDIF

zipcount++
LOOP

Collection-controlled loops

[edit]

Several programming languages (e.g.,Ada,D,C++11,Smalltalk,PHP,Perl,Object Pascal,Java,C#,MATLAB,Visual Basic,Ruby,Python,JavaScript,Fortran 95and later) have special constructs which allow implicit looping through all elements of an array, or all members of a set or collection.

someCollectiondo:[:eachElement |xxx].

forIteminCollectiondobeginxxxend;

foreach(item; myCollection) { xxx }

foreachsomeArray { xxx }

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

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

foreach(stringsinmyStringCollection) { xxx }

someCollection | ForEach-Object { $_ }

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

Scalahasfor-expressions,which generalise collection-controlled loops, and also support other uses, such asasynchronous programming.Haskellhas do-expressions and comprehensions, which together provide similar function to for-expressions in Scala.

General iteration

[edit]

General iteration constructs such as C'sforstatement andCommon Lisp'sdoform can be used to express any of the above sorts of loops, and others, such as looping over some number of collections in parallel. Where a more specific looping construct can be used, it is usually preferred over the general iteration construct, since it often makes the purpose of the expression clearer.

Infinite loops

[edit]

Infinite loopsare 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 aserver) should loop forever, handling events as they occur, only stopping when the process is terminated by an operator.

Infinite loops can be implemented using other control flow constructs. Most commonly, in unstructured programming this is jump back up (goto), while in structured programming this is an indefinite loop (while loop) set to never end, either by omitting the condition or explicitly setting it to true, aswhile (true)....Some languages have special constructs for infinite loops, typically by omitting the condition from an indefinite loop. Examples include Ada (loop... end loop),[7]Fortran (DO... END DO), Go (for {... }), and Ruby (loop do... end).

Often, an infinite loop is unintentionally created by a programming error in a condition-controlled loop, wherein the loop condition uses variables that never change within the loop.

Continuation with next iteration

[edit]

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 ascontinue(most languages),skip,[8]cycle(Fortran), ornext(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

[edit]

Some languages, like Perl[9]and Ruby,[10]have aredostatement that restarts the current iteration from the start.

Restart loop

[edit]

Ruby has aretrystatement that restarts the entire loop from the initial iteration.[11]

Early exit from loops

[edit]

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 asbreak(most languages),Exit(Visual Basic), orlast(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 isloop-and-a-half.

The following example is done inAdawhich supports bothearly exit from loopsandloops with test in the middle.Both features are very similar and comparing both code snippets will show the difference:early exitmust be combined with anifstatement while acondition in the middleis a self-contained construct.

withAda.TextIO;
withAda.IntegerTextIO;

procedurePrint_Squaresis
X:Integer;
begin
Read_Data:loop
Ada.IntegerTextIO.Get(X);
exitRead_DatawhenX=0;
Ada.TextIO.Put(X*X);
Ada.TextIO.New_Line;
endloopRead_Data;
endPrint_Squares;

Pythonsupports conditional execution of code depending on whether a loop was exited early (with abreakstatement) or not by using an else-clause with the loop. For example,

forninset_of_numbers:
ifisprime(n):
print("Set contains a prime number")
break
else:
print("Set did not contain any prime numbers")

Theelseclause in the above example is linked to theforstatement, and not the innerifstatement. Both Python'sforandwhileloops support such an else clause, which is executed only if early exit of the loop has not occurred.

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 ofNlevels), as in bash[12]and PHP,[13]or via labeled breaks (break out and continue at given label), as in Go, Java and Perl.[14]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.[15]Python does not have a multilevel break or continue – this was proposed inPEP 3136,and rejected on the basis that the added complexity was not worth the rare legitimate use.[16]

The notion of multi-level breaks is of some interest intheoretical computer science,because it gives rise to what is today called theKosaraju hierarchy.[17]In 1973S. Rao Kosarajurefined thestructured program theoremby 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.[18]Furthermore, Kosaraju proved that a strict hierarchy of programs exists: for every integern,there exists a program containing a multi-level break of depthnthat cannot be rewritten as a program with multi-level breaks of depth less thannwithout introducing added variables.[17]

One can alsoreturnout of a subroutine executing the looped statements, breaking out of both the nested loop and the subroutine. There are otherproposed control structuresfor multiple breaks, but these are generally implemented as exceptions instead.

In his 2004 textbook,David Wattuses Tennent's notion ofsequencerto explain the similarity between multi-level breaks and return statements. Watt notes that a class of sequencers known asescape 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.[19]

Loop variants and invariants

[edit]

Loop variantsandloop invariantsare used to express correctness of loops.[20]

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 asEiffelcontain native support for loop variants and invariants. In other cases, support is an add-on, such as theJava Modeling Language's specification forloop statementsinJava.

Loop sublanguage

[edit]

SomeLispdialects provide an extensive sublanguage for describing Loops. An early example can be found in Conversional Lisp ofInterlisp.Common Lisp[21]provides a Loop macro which implements such a sublanguage.

Loop system cross-reference table

[edit]
Programming language conditional loop early exit loop continuation redo retry correctness facilities
begin middle end count collection general infinite[1] variant invariant
Ada Yes Yes Yes Yes arrays No Yes deep nested No
APL Yes No Yes Yes Yes Yes Yes deep nested[3] Yes No No
C Yes No Yes No[2] No Yes No deep nested[3] deep nested[3] No
C++ Yes No Yes No[2] Yes[9] Yes No deep nested[3] deep nested[3] No
C# Yes No Yes No[2] Yes Yes No deep nested[3] deep nested[3]
COBOL Yes No Yes Yes No Yes No deep nested[15] deep nested[14] No
Common Lisp Yes Yes Yes Yes builtin only[16] Yes Yes deep nested No
D Yes No Yes Yes Yes Yes Yes[14] deep nested deep nested No
Eiffel Yes No No Yes[10] Yes Yes No one level[10] No No No[11] integer only[13] Yes
F# Yes No No Yes Yes No No No[6] No No
FORTRAN 77 Yes No No Yes No No No one level Yes
Fortran 90 Yes No No Yes No No Yes deep nested Yes
Fortran 95and later Yes No No Yes arrays No Yes deep nested Yes
Go Yes No No Yes builtin only Yes Yes deep nested deep nested No
Haskell No No No No Yes No Yes No[6] No No
Java Yes No Yes No[2] Yes Yes No deep nested deep nested No non-native[12] non-native[12]
JavaScript Yes No Yes No[2] Yes Yes No deep nested deep nested No
Natural Yes Yes Yes Yes No Yes Yes Yes Yes Yes No
OCaml Yes No No Yes arrays,lists No No No[6] No No
PHP Yes No Yes No[2][5] Yes[4] Yes No deep nested deep nested No
Perl Yes No Yes No[2][5] Yes Yes No deep nested deep nested Yes
Python Yes No No No[5] Yes No No deep nested[6] deep nested[6] No
Rebol No[7] Yes Yes Yes Yes No[8] Yes one level[6] No No
Ruby Yes No Yes Yes Yes No Yes deep nested[6] deep nested[6] Yes Yes
Standard ML Yes No No No arrays,lists No No No[6] No No
Visual Basic.NET Yes No Yes Yes Yes No Yes one level per type of loop one level per type of loop
PowerShell Yes No Yes No[2] Yes Yes No ? Yes
  1. awhile (true)does not count as an infinite loop for this purpose, because it is not a dedicated language structure.
  2. abcdefghC'sfor (init;test;increment)loop is a general loop construct, not specifically a counting one, although it is often used for that.
  3. abcDeep breaks may be accomplished in APL, C, C++ and C# through the use of labels and gotos.
  4. aIteration over objects wasaddedin PHP 5.
  5. abcA counting loop can be simulated by iterating over an incrementing list or generator, for instance, Python'srange().
  6. abcdeDeep breaks may be accomplished through the use of exception handling.
  7. aThere is no special construct, since thewhilefunction can be used for this.
  8. aThere is no special construct, but users can define general loop functions.
  9. aTheC++11standard introduced therange-based for.In theSTL,there is astd::for_eachtemplatefunction which can iterate on STLcontainersand call aunary functionfor each element.[22]The functionality also can be constructed asmacroon these containers.[23]
  10. aCount-controlled looping is effected by iteration across an integer interval; early exit by including an additional condition for exit.
  11. aEiffel supports a reserved wordretry,however it is used inexception handling,not loop control.
  12. aRequiresJava Modeling Language(JML) behavioral interface specification language.
  13. aRequires loop variants to be integers; transfinite variants are not supported.[1]
  14. aD supports infinite collections, and the ability to iterate over those collections. This does not require any special construct.
  15. aDeep breaks can be achieved usingGO TOand procedures.
  16. aCommon Lisp predates the concept of generic collection type.

Structured non-local control flow

[edit]

Many programming languages, especially those favoring more dynamic styles of programming, offer constructs fornon-local control flow.These cause the flow of execution to jump out of a given context and resume at some predeclared point.Conditions,exceptionsandcontinuationsare three common sorts of non-local control constructs; more exotic ones also exist, such asgenerators,coroutinesand theasynckeyword.

Conditions

[edit]

PL/Ihas some 22 standard conditions (e.g., ZERODIVIDE SUBSCRIPTRANGE ENDFILE) which can be raised and which can be intercepted by: ONconditionaction; Programmers can also define and use their own named conditions.

Like theunstructured if,only one statement can be specified so in many cases a GOTO is needed to decide where flow of control should resume.

Unfortunately, some implementations had a substantial overhead in both space and time (especially SUBSCRIPTRANGE), so many programmers tried to avoid using conditions.

Common Syntax examples:

ONconditionGOTOlabel

Exceptions

[edit]

Modern languages have a specialized structured construct for exception handling which does not rely on the use ofGOTOor (multi-level) breaks or returns. For example, in C++ one can write:

try{
xxx1// Somewhere in here
xxx2// use: '''throw''' someValue;
xxx3
}catch(someClass&someId){// catch value of someClass
actionForSomeClass
}catch(someType&anotherId){// catch value of someType
actionForSomeType
}catch(...){// catch anything not already caught
actionForAnythingElse
}

Any number and variety ofcatchclauses can be used above. If there is nocatchmatching a particularthrow,control percolates back through subroutine calls and/or nested blocks until a matchingcatchis found or until the end of the main program is reached, at which point the program is forcibly stopped with a suitable error message.

Via C++'s influence,catchis 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 keywordexceptionto introduce an exception handler and then may even employ a different keyword (whenin Ada) for the pattern matching. A few languages likeAppleScriptincorporate placeholders in the exception handler syntax to automatically extract several pieces of information when the exception occurs. This approach is exemplified below by theon errorconstruct from AppleScript:

try
setmyNumbertomyNumber/0
onerrorenumbernfromftotpartialresultpr
if(e="Can't divide by zero")thendisplay dialog"You must not do that"
endtry

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 orinput/outputfailures 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 oppositedefault 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.[24]

In Object Pascal, D, Java, C#, and Python afinallyclause can be added to thetryconstruct. No matter how control leaves thetrythe code inside thefinallyclause 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:

FileStreamstm=null;// C# example
try
{
stm=newFileStream("logfile.txt",FileMode.Create);
returnProcessStuff(stm);// may throw an exception
}
finally
{
if(stm!=null)
stm.Close();
}

Since this pattern is fairly common, C# has a special syntax:

using(varstm=newFileStream("logfile.txt",FileMode.Create))
{
returnProcessStuff(stm);// may throw an exception
}

Upon leaving theusing-block, the compiler guarantees that thestmobject is released, effectivelybindingthe variable to the file stream while abstracting from the side effects of initializing and releasing the file. Python'swithstatement and Ruby's block argument toFile.openare used to similar effect.

All the languages mentioned above define standard exceptions and the circumstances under which they are thrown. Users can throw exceptions of their own; C++ allows users to throw and catch almost any type, including basic types likeint,whereas other languages like Java are less permissive.

Continuations

[edit]

Async

[edit]

C# 5.0 introduced the async keyword for supportingasynchronous I/Oin a "direct style".

Generators

[edit]

Generators,also known as semicoroutines, allow control to be yielded to a consumer method temporarily, typically using ayieldkeyword (yield description). Like the async keyword, this supports programming in a "direct style".

Coroutines

[edit]

Coroutinesare functions that can yield control to each other - a form ofco-operative multitaskingwithout 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

[edit]
Programming language conditions exceptions generators/coroutines async
Ada No Yes ? ?
C No No No No
C++ No Yes Yes ?
C# No Yes Yes Yes
COBOL Yes Yes No No
Common Lisp Yes No ? ?
D No Yes Yes ?
Eiffel No Yes ? ?
Erlang No Yes Yes ?
F# No Yes Yes Yes
Go No Yes Yes ?
Haskell No Yes Yes No
Java No Yes No No
JavaScript ? Yes Yes Yes
Objective-C No Yes No ?
PHP No Yes Yes ?
PL/I Yes No No No
Python No Yes Yes Yes[25]
Rebol Yes Yes No ?
Ruby No Yes Yes via extension[26]
Rust No Yes experimental[27][28] Yes[29]
Scala No Yes via experimental extension[30] via experimental extension
Tcl via traces Yes Yes via event loop
Visual Basic.NET Yes Yes No ?
PowerShell No Yes No ?

Proposed control structures

[edit]

In a spoofDatamationarticle[31]in 1973, R. Lawrence Clark suggested that the GOTO statement could be replaced by theCOMEFROMstatement, and provides some entertaining examples. COMEFROM was implemented in oneesoteric programming languagenamedINTERCAL.

Donald Knuth's 1974 article "Structured Programming with go to Statements",[32]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.

Loop with test in the middle

[edit]

The following was proposed byDahlin 1972:[33]

looploop
xxx1 read(char);
whiletest;whilenotatEndOfFile;
xxx2 write(char);
repeat;repeat;

Ifxxx1is omitted, we get a loop with the test at the top (a traditionalwhileloop). Ifxxx2is omitted, we get a loop with the test at the bottom, equivalent to ado whileloop in many languages. Ifwhileis omitted, we get an infinite loop. The construction here can be thought of as adoloop 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:

while(true) {
xxx1
if(nottest)
break
xxx2
}

A possible variant is to allow more than onewhiletest; within the loop, but the use ofexitwhen(see next section) appears to cover this case better.

InAda,the above loop construct (loop-while-repeat) can be represented using a standard infinite loop (loop-end loop) that has anexit whenclause in the middle (not to be confused with theexitwhenstatement in the following section).

withAda.Text_IO;
withAda.Integer_Text_IO;

procedurePrint_Squaresis
X:Integer;
begin
Read_Data:loop
Ada.Integer_Text_IO.Get(X);
exitRead_DatawhenX=0;
Ada.TextIO.Put(X*X);
Ada.TextIO.New_Line;
endloopRead_Data;
endPrint_Squares;

Naming a loop (likeRead_Datain this example) is optional but permits leaving the outer loop of several nested loops.

Multiple early exit/exit from nested loops

[edit]

This constructwas proposed byZahnin 1974.[34]A modified version is presented here.

exitwhenEventAorEventBorEventC;
xxx
exits
EventA: actionA
EventB: actionB
EventC: actionC
endexit;

exitwhenis used to specify the events which may occur withinxxx, 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 afterendexit.This construction provides a very clear separation between determining that some situation applies, and the action to be taken for that situation.

exitwhenis conceptually similar toexception 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.

exitwhenfoundormissing;
forI:= 1toNdo
forJ:= 1toMdo
iftable[I,J] = targetthenfound;
missing;
exits
found: print ( "item is in table" );
missing: print ( "item is not in table" );
endexit;

Security

[edit]

One way to attack a piece of software is to redirect the flow of execution of a program. A variety ofcontrol-flow integritytechniques, includingstack canaries,buffer overflow protection,shadow stacks, andvtablepointer verification, are used to defend against these attacks.[35][36][37]

See also

[edit]

References

[edit]
  1. ^Böhm, Jacopini. "Flow diagrams, turing machines and languages with only two formation rules"Comm. ACM,9(5):366-371, May 1966.
  2. ^abRoberts, E. [1995] "Loop Exits and Structured Programming: Reopening the DebateArchived2014-07-25 at theWayback Machine,"ACM SIGCSE Bulletin, (27)1: 268–272.
  3. ^David Anthony Watt; William Findlay (2004).Programming language design concepts.John Wiley & Sons. p. 228.ISBN978-0-470-85320-7.
  4. ^"Nested Loops in C with Examples".GeeksforGeeks.2019-11-25.Retrieved2024-03-14.
  5. ^"Python Nested Loops".w3schools.Retrieved2024-03-14.
  6. ^Dean, Jenna (2019-11-22)."Nested Loops".The Startup.Retrieved2024-03-14.
  7. ^Ada Programming: Control: Endless Loop
  8. ^"What is a loop and how we can use them?".Archived fromthe originalon 2020-07-28.Retrieved2020-05-25.
  9. ^"redo - perldoc.perl.org".perldoc.perl.org.Retrieved2020-09-25.
  10. ^"control_expressions - Documentation for Ruby 2.4.0".docs.ruby-lang.org.Retrieved2020-09-25.
  11. ^"control_expressions - Documentation for Ruby 2.3.0".docs.ruby-lang.org.Retrieved2020-09-25.
  12. ^Advanced Bash Scripting Guide:11.3. Loop Control
  13. ^PHP Manual: "break"
  14. ^perldoc:last
  15. ^comp.lang.c FAQ list · "Question 20.20b"
  16. ^[Python-3000] Announcing PEP 3136,Guido van Rossum
  17. ^abKozen, Dexter (2008). "The Böhm–Jacopini Theorem is False, Propositionally".Mathematics of Program Construction(PDF).Lecture Notes in Computer Science. Vol. 5133. pp. 177–192.CiteSeerX10.1.1.218.9241.doi:10.1007/978-3-540-70594-9_11.ISBN978-3-540-70593-2.
  18. ^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 byKnuth, Donald(1974). "Structured Programming with go to Statements".Computing Surveys.6(4): 261–301.CiteSeerX10.1.1.103.6084.doi:10.1145/356635.356640.S2CID207630080.
  19. ^David Anthony Watt; William Findlay (2004).Programming language design concepts.John Wiley & Sons. pp. 215–221.ISBN978-0-470-85320-7.
  20. ^Meyer, Bertrand (1991).Eiffel: The Language.Prentice Hall. pp. 129–131.
  21. ^"Common Lisp LOOP macro".
  22. ^for_each.Sgi. Retrieved on 2010-11-09.
  23. ^Chapter 1. Boost.ForeachArchived2010-01-29 at theWayback Machine.Boost-sandbox.sourceforge.net (2009-12-19). Retrieved on 2010-11-09.
  24. ^David Anthony Watt; William Findlay (2004).Programming language design concepts.John Wiley & Sons. pp. 221–222.ISBN978-0-470-85320-7.
  25. ^"Asyncio: Asynchronous I/O: Python 3.10.2 documentation".
  26. ^"Socketry/Async".GitHub.25 February 2022.
  27. ^"Generators - the Rust Unstable Book".
  28. ^"Corona - Rust".
  29. ^"Getting Started - Asynchronous Programming in Rust".
  30. ^"Jitsi Meet".Storm-enroute.Retrieved2022-09-07.
  31. ^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.Archived2018-07-16 at theWayback MachineBy R. Lawrence Clark* From Datamation, December, 1973
  32. ^Knuth, Donald E. "Structured Programming with go to Statements"ACM Computing Surveys6(4):261-301, December 1974.
  33. ^Dahl & Dijkstra & Hoare, "Structured Programming" Academic Press, 1972.
  34. ^Zahn, C. T. "A control statement for natural top-down structured programming" presented at Symposium on Programming Languages, Paris, 1974.
  35. ^Payer, Mathias;Kuznetsov, Volodymyr."On differences between the CFI, CPS, and CPI properties".nebelwelt.net.Retrieved2016-06-01.
  36. ^"Adobe Flash Bug Discovery Leads To New Attack Mitigation Method".Dark Reading.10 November 2015.Retrieved2016-06-01.
  37. ^Endgame."Endgame to Present at Black Hat USA 2016".prnewswire.Retrieved2016-06-01.

Further reading

[edit]
  • Hoare, C. A. R. "Partition: Algorithm 63," "Quicksort: Algorithm 64," and "Find: Algorithm 65." Comm. ACM 4, 321–322, 1961.
[edit]