Open main menu
Home
Random
Recent changes
Special pages
Community portal
Preferences
About Wikipedia
Disclaimers
Incubator escapee wiki
Search
User menu
Talk
Dark mode
Contributions
Create account
Log in
Editing
Control flow
(section)
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
== Structured non-local control flow == Many programming languages, especially those favoring more dynamic styles of programming, offer constructs for ''non-local control flow''. These cause the flow of execution to jump out of a given context and resume at some [[predeclared]] point. ''[[Exception handling#Condition systems|Conditions]]'', ''[[Exception handling|exceptions]]'' and ''[[continuation]]s'' are three common sorts of non-local control constructs; more exotic ones also exist, such as [[Generator (computer programming)|generators]], [[coroutine]]s and the [[Futures and promises|async]] keyword. === Conditions === The earliest [[Fortran]] compilers had statements for testing exceptional conditions. These included the <code>IF ACCUMULATOR OVERFLOW</code>, <code>IF QUOTIENT OVERFLOW</code>, and <code>IF DIVIDE CHECK</code> statements. In the interest of machine independence, they were not included in FORTRAN IV and the Fortran 66 Standard. However since Fortran 2003 it is possible to test for numerical issues via calls to functions in the <code>IEEE_EXCEPTIONS</code> module. [[PL/I]] has some 22 standard conditions (e.g., ZERODIVIDE SUBSCRIPTRANGE ENDFILE) which can be raised and which can be intercepted by: ON ''condition'' action; Programmers can also define and use their own named conditions. Like the ''unstructured if'', only one statement can be specified so in many cases a GOTO is needed to decide where flow of control should resume. Unfortunately, some implementations had a substantial overhead in both space and time (especially SUBSCRIPTRANGE), so many programmers tried to avoid using conditions. Common Syntax examples: '''ON''' ''condition'' '''GOTO''' ''label'' === Exceptions === {{main article|Exception handling}} Modern languages have a specialized structured construct for exception handling which does not rely on the use of <code>GOTO</code> or (multi-level) breaks or returns. For example, in C++ one can write: <syntaxhighlight lang="cpp"> try { xxx1 // Somewhere in here xxx2 // use: '''throw''' someValue; xxx3 } catch (someClass& someId) { // catch value of someClass actionForSomeClass } catch (someType& anotherId) { // catch value of someType actionForSomeType } catch (...) { // catch anything not already caught actionForAnythingElse } </syntaxhighlight> Any number and variety of <code>catch</code> clauses can be used above. If there is no <code>catch</code> matching a particular <code>throw</code>, control percolates back through subroutine calls and/or nested blocks until a matching <code>catch</code> is found or until the end of the main program is reached, at which point the program is forcibly stopped with a suitable error message. Via C++'s influence, <code>catch</code> is the keyword reserved for declaring a pattern-matching exception handler in other languages popular today, like Java or C#. Some other languages like Ada use the keyword <code>exception</code> to introduce an exception handler and then may even employ a different keyword (<code>when</code> in Ada) for the pattern matching. A few languages like [[AppleScript]] incorporate placeholders in the exception handler syntax to automatically extract several pieces of information when the exception occurs. This approach is exemplified below by the <code>on error</code> construct from AppleScript:<!-- Here, it would help to explain what all those "from", "to", and "partial results" bits do.--> <syntaxhighlight lang = "applescript"> try set myNumber to myNumber / 0 on error e number n from f to t partial result pr if ( e = "Can't divide by zero" ) then display dialog "You must not do that" end try </syntaxhighlight> David Watt's 2004 textbook also analyzes exception handling in the framework of sequencers (introduced in this article in the section on early exits from loops). Watt notes that an abnormal situation, generally exemplified with arithmetic overflows or [[input/output]] failures like file not found, is a kind of error that "is detected in some low-level program unit, but [for which] a handler is more naturally located in a high-level program unit". For example, a program might contain several calls to read files, but the action to perform when a file is not found depends on the meaning (purpose) of the file in question to the program and thus a handling routine for this abnormal situation cannot be located in low-level system code. Watts further notes that introducing status flags testing in the caller, as single-exit structured programming or even (multi-exit) return sequencers would entail, results in a situation where "the application code tends to get cluttered by tests of status flags" and that "the programmer might forgetfully or lazily omit to test a status flag. In fact, abnormal situations represented by status flags are by default ignored!" Watt notes that in contrast to status flags testing, exceptions have the opposite [[Default (computer science)|default behavior]], causing the program to terminate unless the program deals with the exception explicitly in some way, possibly by adding explicit code to ignore it. Based on these arguments, Watt concludes that jump sequencers or escape sequencers are less suitable as a dedicated exception sequencer with the semantics discussed above.<ref>{{cite book|author1=David Anthony Watt|author2=William Findlay|title=Programming language design concepts|year=2004|publisher=John Wiley & Sons|isbn=978-0-470-85320-7|pages=221β222}}</ref> In Object Pascal, D, Java, C#, and Python a <code>finally</code> clause can be added to the <code>try</code> construct. No matter how control leaves the <code>try</code> the code inside the <code>finally</code> clause is guaranteed to execute. This is useful when writing code that must relinquish an expensive resource (such as an opened file or a database connection) when finished processing: <syntaxhighlight lang="csharp"> FileStream stm = null; // C# example try { stm = new FileStream("logfile.txt", FileMode.Create); return ProcessStuff(stm); // may throw an exception } finally { if (stm != null) stm.Close(); } </syntaxhighlight> Since this pattern is fairly common, C# has a special syntax: <syntaxhighlight lang="csharp"> using (var stm = new FileStream("logfile.txt", FileMode.Create)) { return ProcessStuff(stm); // may throw an exception } </syntaxhighlight> Upon leaving the <code>using</code>-block, the compiler guarantees that the <code>stm</code> object is released, effectively [[Name binding|binding]] the variable to the file stream while abstracting from the side effects of initializing and releasing the file. Python's <code>with</code> statement and Ruby's block argument to <code>File.open</code> are used to similar effect. All the languages mentioned above define standard exceptions and the circumstances under which they are thrown. Users can throw exceptions of their own; C++ allows users to throw and catch almost any type, including basic types like <code>int</code>, whereas other languages like Java are less permissive. === Continuations === {{main article|Continuation}} === Async === C# 5.0 introduced the async keyword for supporting [[asynchronous I/O]] in a "direct style". === Generators === {{Main|Generator (computer science)}} [[Generator (computer science)|Generators]], also known as semicoroutines, allow control to be yielded to a consumer method temporarily, typically using a {{Python|yield}} keyword ([https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/yield yield description]) . Like the async keyword, this supports programming in a "direct style". === Coroutines === {{Main|Coroutine}} [[Coroutines]] are functions that can yield control to each other - a form of [[co-operative multitasking]] without threads. Coroutines can be implemented as a library if the programming language provides either continuations or generators - so the distinction between coroutines and generators in practice is a technical detail. === Non-local control flow cross reference === {| class="wikitable" |- ! [[Programming language]] ! conditions ! exceptions ! generators/coroutines ! async |- | [[Ada (programming language)|Ada]] | {{no}} | {{yes}} | {{dunno}} | {{dunno}} |- | [[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}} |}
Edit summary
(Briefly describe your changes)
By publishing changes, you agree to the
Terms of Use
, and you irrevocably agree to release your contribution under the
CC BY-SA 4.0 License
and the
GFDL
. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license.
Cancel
Editing help
(opens in new window)