Flow-control structures: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎CATCH-THROW: Better sentence)
m (Fixed lang tags.)
Line 6: Line 6:


===goto===
===goto===
<lang ada> <<Top>>
<lang ada><<Top>>
Put_Line("Hello, World");
Put_Line("Hello, World");
goto Top;</lang>
goto Top;</lang>


===exit===
===exit===
Exit is used to break out of loops. Exit can be used with a label to break out of an inner loop to an outer loop and its enclosing outer loop
Exit is used to break out of loops. Exit can be used with a label to break out of an inner loop to an outer loop and its enclosing outer loop
<lang ada> Outer:
<lang ada>Outer:
loop
loop
-- do something
-- do something
loop
loop
-- do something else
-- do something else
exit Outer; -- exits both the inner and outer loops
exit Outer; -- exits both the inner and outer loops
end loop;
end loop;
end loop;</lang>
end loop;</lang>
===asynchronous transfer of control===
===asynchronous transfer of control===
A sequence of operation can be aborted with an asynchronous transfer of control to an alternative:
A sequence of operation can be aborted with an asynchronous transfer of control to an alternative:
<lang ada>
<lang ada>select
select
delay 10.0;
delay 10.0;
Put_Line ("Cannot finish this in 10s");
Put_Line ("Cannot finish this in 10s");
Line 29: Line 28:
-- do some lengthy calculation
-- do some lengthy calculation
...
...
end select;
end select;</lang>
</lang>
The alternative can be a delay statement or else an entry point call followed by a sequence of operations. The statement blocks at the delay or entry call and executes the sequence of the operation introduced by '''then abort'''. If blocking is lifted before completion of the sequence, the sequence is aborted and the control is transferred there.
The alternative can be a delay statement or else an entry point call followed by a sequence of operations. The statement blocks at the delay or entry call and executes the sequence of the operation introduced by '''then abort'''. If blocking is lifted before completion of the sequence, the sequence is aborted and the control is transferred there.


Line 41: Line 39:
See also [[Exceptions#ALGOL_68|Exceptions]] to see how '''ALGOL 68''' handles ''transput'' events.
See also [[Exceptions#ALGOL_68|Exceptions]] to see how '''ALGOL 68''' handles ''transput'' events.
===One common use of a label in '''ALGOL 68''' is to break out of nested loops.===
===One common use of a label in '''ALGOL 68''' is to break out of nested loops.===
<lang algol>(
<lang algol68>(
FOR j TO 1000 DO
FOR j TO 1000 DO
FOR i TO j-1 DO
FOR i TO j-1 DO
Line 54: Line 52:
);</lang>
);</lang>
===Multi way jump using labels and '''EXIT''' to return result ===
===Multi way jump using labels and '''EXIT''' to return result ===
<lang algol>STRING medal = (
<lang algol68>STRING medal = (
[]PROC VOID award = (gold,silver,bronze);
[]PROC VOID award = (gold,silver,bronze);


Line 67: Line 65:
print(("Medal awarded: ",medal, new line));</lang>
print(("Medal awarded: ",medal, new line));</lang>
===Another use is to implement finite state machines ===
===Another use is to implement finite state machines ===
<lang algol>STRING final state = (
<lang algol68>STRING final state = (
INT condition;
INT condition;
PROC do something = VOID: condition := 1 + ENTIER (3 * random);
PROC do something = VOID: condition := 1 + ENTIER (3 * random);
Line 89: Line 87:
print(("Final state: ",final state, new line));</lang>
print(("Final state: ",final state, new line));</lang>
===ALGOL 68G implements a Refinement Preprocessor to aid with top down code development ===
===ALGOL 68G implements a Refinement Preprocessor to aid with top down code development ===
<lang algol># example from: http://www.xs4all.nl/~jmvdveer/algol.html - GPL #
<lang algol68># example from: http://www.xs4all.nl/~jmvdveer/algol.html - GPL #
determine first generation;
determine first generation;
WHILE can represent next generation
WHILE can represent next generation
Line 150: Line 148:
===goto===
===goto===
One common use of goto in C is to break out of nested loops.
One common use of goto in C is to break out of nested loops.
<lang c> int main()
<lang c>int main()
{
{
int i,j;
int i,j;
for (j=1; j<1000; j++) {
for (j=1; j<1000; j++) {
for (i=0; i<j, i++) {
for (i=0; i<j, i++) {
if (exit_early())
if (exit_early())
goto out;
goto out;
/* etc. */
/* etc. */
}
}
}
}
out:
out:
return 0;
return 0;
}</lang>
}</lang>


=={{header|C++}}==
=={{header|C++}}==
=== goto ===
=== goto ===
{{works with|GCC|3.3.4}}
{{works with|GCC|3.3.4}}
<lang cpp> #include <iostream>
<lang cpp>#include <iostream>

int main()
int main()
{
{
LOOP:
LOOP:
std::cout << "Hello, World!\n";
std::cout << "Hello, World!\n";
goto LOOP;
goto LOOP;
}</lang>
}</lang>


Note that "goto" may also be used in conjunction with other forms of branching.
Note that "goto" may also be used in conjunction with other forms of branching.
Line 182: Line 180:


Exceptions are a way to give control back to a direct or indirect caller in case of an error. Note that throwing exceptions is usually very expensive, therefore they generally should only be used for exceptional situations.
Exceptions are a way to give control back to a direct or indirect caller in case of an error. Note that throwing exceptions is usually very expensive, therefore they generally should only be used for exceptional situations.
<lang cpp> #include <iostream>
<lang cpp>#include <iostream>
#include <ostream>
#include <ostream>

void foo()
void foo()
{
{
std::cout << "Going to throw an exception.\n";
std::cout << "Going to throw an exception.\n";
throw 7; // almost any object can be thrown, including ints
throw 7; // almost any object can be thrown, including ints
std::throw << "This output will never execute.\n";
std::throw << "This output will never execute.\n";
}
}

void bar()
void bar()
{
{
std::cout << "Going to call foo().\n";
std::cout << "Going to call foo().\n";
foo();
foo();
std::cout << "This will be skipped by the exception coming from foo.\n";
std::cout << "This will be skipped by the exception coming from foo.\n";
}
}

void baz()
void baz()
{
{
try // everything thrown from inside the following code block
try // everything thrown from inside the following code block
{ // will be covered by the following catch clauses
{ // will be covered by the following catch clauses
std::cout << "Going to call bar().\n";
std::cout << "Going to call bar().\n";
bar();
bar();
std::cout << "This will be skipped by the exception coming from foo.\n";
std::cout << "This will be skipped by the exception coming from foo.\n";
}
}
catch(...) // a simple catch-all, but doesn't give access to the thrown exception
catch(...) // a simple catch-all, but doesn't give access to the thrown exception
{
{
std::cout << "An exception occured. I'll just throw it on.\n";
std::cout << "An exception occured. I'll just throw it on.\n";
throw; // without an argument, the caught exception is re-thrown
throw; // without an argument, the caught exception is re-thrown
}
}
std::cout << "This will not be executed due to the re-throw in the catch block\n";
std::cout << "This will not be executed due to the re-throw in the catch block\n";
}
}

void foobar()
void foobar()
{
{
try
try
{
{
baz();
baz();
}
}
catch(char const* s)
catch(char const* s)
{
{
std::cout << "If foo had thrown a char const*, this code would be executed.\n";
std::cout << "If foo had thrown a char const*, this code would be executed.\n";
std::cout << "In that case, the thrown char const* would read " << s << ".\n";
std::cout << "In that case, the thrown char const* would read " << s << ".\n";
}
}
catch(int i)
catch(int i)
{
{
std::cout << "Caught an int, with value " << i << " (should be 7).\n";
std::cout << "Caught an int, with value " << i << " (should be 7).\n";
std::cout << "Not rethrowing the int.\n";
std::cout << "Not rethrowing the int.\n";
}
}
catch(...)
catch(...)
{
{
std::cout << "This catch-all doesn't get invoked because the catch(int) above\n"
std::cout << "This catch-all doesn't get invoked because the catch(int) above\n"
<< "already took care of the exception (even if it had rethrown the\n"
<< "already took care of the exception (even if it had rethrown the\n"
<< "exception, this catch-all would not be invoked, because it's\n"
<< "exception, this catch-all would not be invoked, because it's\n"
<< "only invoked for exceptions coming from the try block.\n";
<< "only invoked for exceptions coming from the try block.\n";
}
}
std::cout << "This will be executed, since the exception was handled above, and not rethrown.\n";
std::cout << "This will be executed, since the exception was handled above, and not rethrown.\n";
}
}

int main()
int main()
{
{
try
try
{
{
foobar();
foobar();
}
}
catch(...)
catch(...)
{
{
std::cout << "The main function never sees the exception, because it's completely handled\n"
std::cout << "The main function never sees the exception, because it's completely handled\n"
<< "inside foobar(). Thus this catch-all block never gets invoked.\n";
<< "inside foobar(). Thus this catch-all block never gets invoked.\n";
}
}
}</lang>
}</lang>


=={{header|D}}==
=={{header|D}}==
=== goto ===
=== goto ===
<lang d>
<lang d>label1:
label1:
writeln ("i'm in your infinite loop");
writeln ("i'm in your infinite loop");
goto label1;
goto label1;</lang>
</lang>


=== Exceptions ===
=== Exceptions ===
D supports standard try/catch/finally mechanisms:
D supports standard try/catch/finally mechanisms:
<lang d>
<lang d>void main (char[][] args)
void main (char[][] args)
{
{
try
try
Line 289: Line 284:
writeln ("finished (exception or none)");
writeln ("finished (exception or none)");
}
}
}</lang>
}
</lang>


=== Scope guards ===
=== Scope guards ===
Line 298: Line 292:


For instance:
For instance:
<lang d>
<lang d>void main (char[][] args)
void main (char[][] args)
{
{
scope (exit) writeln ("gone");
scope (exit) writeln ("gone");
if (args[1] == "throw") throw new Exception ("message");
if (args[1] == "throw") throw new Exception ("message");
scope (exit) writeln ("gone, but we passed the first chance to throw an exception");
scope (exit) writeln ("gone, but we passed the first chance to throw an exception");
}</lang>
}
</lang>


If the exception is thrown, then the only text that is written to the screen is "gone". If no exception is thrown, both calls to writeln occur.
If the exception is thrown, then the only text that is written to the screen is "gone". If no exception is thrown, both calls to writeln occur.
Line 317: Line 309:
The basic syntax is
The basic syntax is


escape ''ej'' {
<lang e>escape ''ej'' {
''...body...''
''...body...''
}</lang>
}


Within ''body'' variable ''ej'' then contains a one-argument function (an ejector) which, if called, immediately returns the provided value from the escape block.
Within ''body'' variable ''ej'' then contains a one-argument function (an ejector) which, if called, immediately returns the provided value from the escape block.
Line 350: Line 342:
===goto===
===goto===


test:
<lang idl>test:
..some code here
..some code here
goto, test
goto, test</lang>


(This is almost never used)
(This is almost never used)
Line 358: Line 350:
===on_error===
===on_error===


on_error, test
<lang idl>on_error, test</lang>


(This resumes at the label <tt>test</tt> if an error is encountered)
(This resumes at the label <tt>test</tt> if an error is encountered)
Line 364: Line 356:
===on_ioerror===
===on_ioerror===


on_ioerror, test
<lang idl>on_ioerror, test</lang>


(Same as <tt>on_error</tt>, but for EOFs and read-errors and such)
(Same as <tt>on_error</tt>, but for EOFs and read-errors and such)
Line 370: Line 362:
===break===
===break===


break
<lang idl>break</lang>


immediately terminates the innermost current loop (or <tt>if</tt> or <tt>case</tt> etc)
immediately terminates the innermost current loop (or <tt>if</tt> or <tt>case</tt> etc)
Line 376: Line 368:
===continue===
===continue===


continue
<lang idl>continue</lang>


immediately starts the next iteration of the current innermost loop
immediately starts the next iteration of the current innermost loop
Line 399: Line 391:
Goto is typically looked down upon by most Perl programmers
Goto is typically looked down upon by most Perl programmers


<lang perl> FORK:
<lang perl>FORK:
# some code
# some code
goto FORK;</lang>
goto FORK;</lang>


=={{header|Pop11}}==
=={{header|Pop11}}==
Line 408: Line 400:
quitloop with argument exits from nested loops:
quitloop with argument exits from nested loops:


<lang pop11>while condition1 do
<pre>
while condition1 do
while condition2 do
while condition2 do
if condition3 then
if condition3 then
Line 415: Line 406:
endif;
endif;
endwhile;
endwhile;
endwhile;
endwhile;</lang>
</pre>


above quitloop(2) exits from both loops.
above quitloop(2) exits from both loops.
Line 425: Line 415:
nested loops:
nested loops:


<lang pop11>while condition1 do
<pre>
while condition1 do
while condition2 do
while condition2 do
if condition3 then
if condition3 then
Line 433: Line 422:
endwhile;
endwhile;
endwhile;
endwhile;
l:;
l:;</lang>
</pre>


Another use is to implement finite state machines:
Another use is to implement finite state machines:


<lang pop11>state1:
<pre>
state1:
DO_SOMETHING();
DO_SOMETHING();
if condition1 then
if condition1 then
Line 454: Line 441:
...
...
stateN:
stateN:
....
....</lang>
</pre>


Pop11 goto is a nonlocal one, so "jump out" from a chain of procedure calls:
Pop11 goto is a nonlocal one, so "jump out" from a chain of procedure calls:


<lang pop11>define outer();
<pre>
define outer();
define inner(n);
define inner(n);
if n = 0 then
if n = 0 then
Line 469: Line 454:
inner(5);
inner(5);
final:;
final:;
enddefine;
enddefine;</lang>
</pre>


This is useful to exit early from successful recursive search, and for exception handling.
This is useful to exit early from successful recursive search, and for exception handling.
Line 478: Line 462:
go_on is a multiway jump
go_on is a multiway jump


<lang pop11>go_on expression to lab1, lab2, ..., labN else elselab ;</lang>
<pre>
go_on expression to lab1, lab2, ..., labN else elselab ;
</pre>


If expression has value K the above will jump to label labK, if expression is not an integer, or if it outside range from 1 to N, then control passes to label elselab. The else part may be omitted (then out of range values of expression cause an exception).
If expression has value K the above will jump to label labK, if expression is not an integer, or if it outside range from 1 to N, then control passes to label elselab. The else part may be omitted (then out of range values of expression cause an exception).
Line 499: Line 481:
it is just:
it is just:


<lang pop11>return;</lang>
<pre>
return;
</pre>


but it is also possible to specify one or more return values:
but it is also possible to specify one or more return values:


<lang pop11>return(val1, val2, val3);</lang>
<pre>
return(val1, val2, val3);
</pre>


===chain===
===chain===
Line 513: Line 491:
chain has effect of "tail call" but is not necessarily in tail position. More precisely inside proc1.
chain has effect of "tail call" but is not necessarily in tail position. More precisely inside proc1.


<lang pop11>chain proc2(x1, x2, x3);</lang>
<pre>
chain proc2(x1, x2, x3);
</pre>


finishes execution of proc1 and transfers control to the proc2 passing it x1, x2, and x3 as arguments. On return from proc2 control passes to caller of proc1.
finishes execution of proc1 and transfers control to the proc2 passing it x1, x2, and x3 as arguments. On return from proc2 control passes to caller of proc1.
Line 524: Line 500:
===Loops===
===Loops===
Python supports ''break'' and ''continue'' to exit from a loop early or short circuit the rest of a loop's body and "continue" on to the next loop iteration.
Python supports ''break'' and ''continue'' to exit from a loop early or short circuit the rest of a loop's body and "continue" on to the next loop iteration.
<lang python>
<lang python># Search for an odd factor of a using brute force:
# Search for an odd factor of a using brute force:
for i in range(n):
for i in range(n):
if (n%2) == 0:
if (n%2) == 0:
Line 534: Line 509:
else:
else:
result = None
result = None
print "No odd factors found"
print "No odd factors found"</lang>
</lang>
In addition, as shown in the foregoing example, Python loops support an ''else:'' suite which can be used to handle cases when the loop was intended to search for something, where the code would break out of the loop upon finding its target. In that situation the ''else:'' suite can be used to handle the failure. (In most other languages one is forced to use a "sentinel value" or a special flag variable ... typically set to "False" before the loop and conditionally set to "True" within the loop to handle situations for which the Python ''else:'' on loops is intended).
In addition, as shown in the foregoing example, Python loops support an ''else:'' suite which can be used to handle cases when the loop was intended to search for something, where the code would break out of the loop upon finding its target. In that situation the ''else:'' suite can be used to handle the failure. (In most other languages one is forced to use a "sentinel value" or a special flag variable ... typically set to "False" before the loop and conditionally set to "True" within the loop to handle situations for which the Python ''else:'' on loops is intended).


Line 548: Line 522:
A custom Exception class is normally declared with the ''pass'' statement as no methods of the parent class are over-ridden, no additional functionality is defined and no attributes need be set. Example:
A custom Exception class is normally declared with the ''pass'' statement as no methods of the parent class are over-ridden, no additional functionality is defined and no attributes need be set. Example:


<lang python>
<lang python>class MyException(Exception): pass</lang>
class MyException(Exception): pass
</lang>


One normally would choose the most similar existing class. For example if MyException was going to be raised for some situation involving an invalid value it might be better to make it a subclass of ValueError; if it was somehow related to issues with inappropriate objects being passed around then one might make it a subclass of TypeError.
One normally would choose the most similar existing class. For example if MyException was going to be raised for some situation involving an invalid value it might be better to make it a subclass of ValueError; if it was somehow related to issues with inappropriate objects being passed around then one might make it a subclass of TypeError.
Line 558: Line 530:
To create a "virtual base class" (one which is not intended to be directly instantiated, but exists solely to provide an inheritance to it's derived classes) one normally defines the requisite methods to raise "NotImplementedError" like so:
To create a "virtual base class" (one which is not intended to be directly instantiated, but exists solely to provide an inheritance to it's derived classes) one normally defines the requisite methods to raise "NotImplementedError" like so:


<lang python>
<lang python>class MyVirtual(object):
class MyVirtual(object):
def __init__(self):
def __init__(self):
raise NotImplementedError
raise NotImplementedError</lang>
</lang>


It then becomes necessary for any descendants of this class to over-ride the ''__init__()'' method. Any attempt to instantiate a "MyVirtual" object directly will raise an exception.
It then becomes necessary for any descendants of this class to over-ride the ''__init__()'' method. Any attempt to instantiate a "MyVirtual" object directly will raise an exception.


====Case 1 - Try, Except====
====Case 1 - Try, Except====
<lang python>
<lang python>try:
try:
temp = 0/0
# 'except' catches any errors that may have been raised between the code of 'try' and 'except'
temp = 0/0
except: # Note: catch all handler ... NOT RECOMMENDED
# 'except' catches any errors that may have been raised between the code of 'try' and 'except'
print "An error occurred."
except: # Note: catch all handler ... NOT RECOMMENDED
print "An error occurred."
# Output : "An error occurred"</lang>
# Output : "An error occurred"
</lang>
====Case 2 - Try, Except====
====Case 2 - Try, Except====
<lang python>
<lang python>try:
try:
temp = 0/0
# here, 'except' catches a specific type of error raised within the try block.
temp = 0/0
except ZeroDivisionError:
# here, 'except' catches a specific type of error raised within the try block.
print "You've divided by zero!"
except ZeroDivisionError:
print "You've divided by zero!"
# Output : "You've divided by zero!"</lang>
# Output : "You've divided by zero!"
</lang>
====Case 3 - Try, Except, Finally====
====Case 3 - Try, Except, Finally====
<lang python>
<lang python>try:
try:
temp = 0/0
except:
temp = 0/0
print "An error occurred."
except:
# here, 'finally' executes when the try - except block ends, regardless of whether an error was raised or not
print "An error occurred."
# here, 'finally' executes when the try - except block ends, regardless of whether an error was raised or not
# useful in areas such as closing opened file streams in the try block whether they were successfully opened or not
finally:
# useful in areas such as closing opened file streams in the try block whether they were successfully opened or not
print "End of 'try' block..."
finally:
# Output :
print "End of 'try' block..."
# An error occurred
# Output :
# End of 'try' block...</lang>
# An error occurred
# End of 'try' block...
</lang>


Note: Prior to version 2.5 a ''try:'' statement could contain either series of ''except:'' clauses '''or''' a ''finally:'' clause but '''not both.''' It was thus necessary to nest the exception handling in an enclosing ''try:''...''finally:'' loop like so:
Note: Prior to version 2.5 a ''try:'' statement could contain either series of ''except:'' clauses '''or''' a ''finally:'' clause but '''not both.''' It was thus necessary to nest the exception handling in an enclosing ''try:''...''finally:'' loop like so:


<lang python>
<lang python>try:
try:
try:
try:
pass
except (MyException1, MyOtherException):
pass
pass
except (MyException1, MyOtherException):
except SomeOtherException:
pass
finally:
except SomeOtherException:
do_some_cleanup() # run in any case, whether any exceptions were thrown or not</lang>
finally:
do_some_cleanup() # run in any case, whether any exceptions were thrown or not
</lang>
====Case 4 - Try, Except, Else====
====Case 4 - Try, Except, Else====
<lang python>
<lang python>try:
temp = 1/1 # not a division by zero error
except ZeroDivisionError: # so... it is not caught
print "You've divided by zero."
# here, 'else' executes when no exceptions are caught...
else:
print "No apparent error occurred."
# Output :
# No apparent error occurred.</lang>
====Case 5 - Try, Except, break, continue====
<lang python>i = 0
while 1: # infinite loop
try:
try:
temp = 1/1 # not a division by zero error
temp2 = 0/i # will raise a ZeroDivisionError first.
temp = math.sqrt(i)
except ZeroDivisionError: # so... it is not caught
print "You've divided by zero."
# here, 'else' executes when no exceptions are caught...
break # 'break' will break out of the while loop
else:
except ValueError: #
print "No apparent error occurred."
print "Imaginary Number! Breaking out of loop"
break # 'break' out of while loop
# Output :
except ZeroDivisionError:
# No apparent error occurred.
print "You've divided by zero. Decrementing i and continuing..."
</lang>
i-=1 # we decrement i.
====Case 5 - Try, Except, break, continue====
# we 'continue', everything within the try - except block will be executed again,
<lang python>
# this time however, ZeroDivisionError would not be raised again.
i = 0
continue # Note that removing it, replacing it with 'pass' would perform the equivalent
while 1: # infinite loop
# see below for a better example
try:
# Output :
temp2 = 0/i # will raise a ZeroDivisionError first.
# You've divided by zero. Decrementing i and continuing...
temp = math.sqrt(i)
# Imaginary Number! Breaking out of loop</lang>
break # 'break' will break out of the while loop
except ValueError: #
print "Imaginary Number! Breaking out of loop"
break # 'break' out of while loop
except ZeroDivisionError:
print "You've divided by zero. Decrementing i and continuing..."
i-=1 # we decrement i.
# we 'continue', everything within the try - except block will be executed again,
# this time however, ZeroDivisionError would not be raised again.
continue # Note that removing it, replacing it with 'pass' would perform the equivalent
# see below for a better example
# Output :
# You've divided by zero. Decrementing i and continuing...
# Imaginary Number! Breaking out of loop
</lang>
====Case 6 - Creating your own custom exceptions, raise====
====Case 6 - Creating your own custom exceptions, raise====
<lang python># Let's call our custom error "StupidError"; it inherits from the Exception class
<lang python>

# Let's call our custom error "StupidError"; it inherits from the Exception class
class StupidError(Exception): pass
class StupidError(Exception): pass
# Try it out.
try:
# Try it out.
raise StupidError("Segfault") # here, we manually 'raise' the error within the try block
try:
raise StupidError("Segfault") # here, we manually 'raise' the error within the try block
except StupidError, details: # 'details' is the StupidError object we create in the try block.
except StupidError, details: # 'details' is the StupidError object we create in the try block.
print 'Something stupid occurred:', details # so we access the value we had stored for it...
print 'Something stupid occurred:', details # so we access the value we had stored for it...

# Output :
# Something stupid occurred: Segfault</lang>
# Output :
# Something stupid occurred: Segfault
</lang>


===Case 7 - continue, else in "for" loop===
===Case 7 - continue, else in "for" loop===
<lang python>
<lang python> i = 101
i = 101
for i in range(4): # loop 4 times
for i in range(4): # loop 4 times
print "I will always be seen."
print "I will always be seen."
Line 684: Line 639:
if(__name__ == "__main__"):
if(__name__ == "__main__"):
main()
main()</lang>
</lang>


===The "with" statement===
===The "with" statement===
Line 691: Line 645:
See [[http://www.python.org/peps/pep-0343.html PEP 0343, The "with" statement]]
See [[http://www.python.org/peps/pep-0343.html PEP 0343, The "with" statement]]


<lang python>
<lang python>class Quitting(Exception): pass
max = 10
class Quitting(Exception): pass
with open("some_file") as myfile:
max = 10
exit_counter = 0
with open("some_file") as myfile:
exit_counter = 0
for line in myfile:
for line in myfile:
exit_counter += 1
exit_counter += 1
if exit_counter > max:
if exit_counter > max:
raise Quitting
raise Quitting
print line,</lang>
print line,
</lang>


The ''with'' statement allows classes to encapsulate "final" (clean-up) code which will automatically be executed regardless of exceptions that occur when working "with" these objects. Thus, for the foregoing example, the file will be closed regardless of whether it's more than 10 lines long. Many built-in and standard library classes have "context managers" which facilitate their use in ''with:'' code. In addition it's possible to define special __enter__() and __exit__() methods in one's own classes which will be implicitly called by the interpreter when an object is used within a ''with:'' statement.
The ''with'' statement allows classes to encapsulate "final" (clean-up) code which will automatically be executed regardless of exceptions that occur when working "with" these objects. Thus, for the foregoing example, the file will be closed regardless of whether it's more than 10 lines long. Many built-in and standard library classes have "context managers" which facilitate their use in ''with:'' code. In addition it's possible to define special __enter__() and __exit__() methods in one's own classes which will be implicitly called by the interpreter when an object is used within a ''with:'' statement.
Line 835: Line 787:
This skips the line that changes the value of x to 5.
This skips the line that changes the value of x to 5.


<lang vb> Sub bar2()
<lang vbnet> Sub bar2()
Dim x = 0
Dim x = 0
GoTo label
GoTo label
x = 5
x = 5
label:
label:
Console.WriteLine(x)
Console.WriteLine(x)
End Sub</lang>
End Sub</lang>


=== On Error Goto ===
=== On Error Goto ===
Line 847: Line 799:
This brances in the event of an error. Usually there is an Exit (Sub|Function) to seperate the normal code from the error handling code
This brances in the event of an error. Usually there is an Exit (Sub|Function) to seperate the normal code from the error handling code


<lang vb> Sub foo()
<lang vbnet> Sub foo()
On Error GoTo label
On Error GoTo label
'do something dangerous
'do something dangerous
Exit Sub
Exit Sub
label:
label:
Console.WriteLine("Operation Failed")
Console.WriteLine("Operation Failed")
End Sub</lang>
End Sub</lang>


''This style of code is rarely used.''
''This style of code is rarely used.''
Line 861: Line 813:
This performs a sequence of actions. If any action fails, the exception is discarded and next operation is performed.
This performs a sequence of actions. If any action fails, the exception is discarded and next operation is performed.


<lang vb> Sub foo2()
<lang vbnet>Sub foo2()
On Error Resume Next
On Error Resume Next
Operation1()
Operation1()
Operation2()
Operation2()
Operation3()
Operation3()
Operation4()
Operation4()
End Sub</lang>
End Sub</lang>


''This style of code is rarely used.''
''This style of code is rarely used.''
Line 875: Line 827:
This shows the classical and modern syntax for exiting a sub routine early.
This shows the classical and modern syntax for exiting a sub routine early.


<lang vb> Sub Foo1()
<lang vbnet>Sub Foo1()
If Not WorkNeeded() Then Exit Sub
If Not WorkNeeded() Then Exit Sub
DoWork()
DoWork()
End Sub
End Sub
Sub Foo2()
Sub Foo2()
If Not WorkNeeded() Then Return
If Not WorkNeeded() Then Return
DoWork()
DoWork()
End Sub</lang>
End Sub</lang>


=== Return value / Exit Function ===
=== Return value / Exit Function ===
Line 889: Line 841:
This shows the classical and modern syntax for exiting a function early. There is an implied variable with the same name as the function. This variable is write-only.
This shows the classical and modern syntax for exiting a function early. There is an implied variable with the same name as the function. This variable is write-only.


<lang vb> Function Foo3()
<lang vbnet>Function Foo3()
Foo3 = CalculateValue()
Foo3 = CalculateValue()
If Not MoreWorkNeeded() Then Exit Function
If Not MoreWorkNeeded() Then Exit Function
Foo3 = CalculateAnotherValue()
Foo3 = CalculateAnotherValue()
End Function
End Function
Function Foo4()
Function Foo4()
Dim result = CalculateValue()
Dim result = CalculateValue()
If Not MoreWorkNeeded() Then Return result
If Not MoreWorkNeeded() Then Return result
Return CalculateAnotherValue()
Return CalculateAnotherValue()
End Function</lang>
End Function</lang>

Revision as of 14:18, 20 November 2009

Task
Flow-control structures
You are encouraged to solve this task according to the task description, using any language you may know.
Control Structures

These are examples of control structures. You may also be interested in:

In this task, we document common flow-control structures. One common example of a flow-control structure is the goto construct. Note that Conditional Structures and Loop Structures have their own articles/categories.

Ada

goto

<lang ada><<Top>>

  Put_Line("Hello, World");
  goto Top;</lang>

exit

Exit is used to break out of loops. Exit can be used with a label to break out of an inner loop to an outer loop and its enclosing outer loop <lang ada>Outer:

  loop
     -- do something
     loop
        -- do something else
        exit Outer; -- exits both the inner and outer loops
     end loop;
  end loop;</lang>

asynchronous transfer of control

A sequence of operation can be aborted with an asynchronous transfer of control to an alternative: <lang ada>select

  delay 10.0;
  Put_Line ("Cannot finish this in 10s");

then abort

  -- do some lengthy calculation
  ...

end select;</lang> The alternative can be a delay statement or else an entry point call followed by a sequence of operations. The statement blocks at the delay or entry call and executes the sequence of the operation introduced by then abort. If blocking is lifted before completion of the sequence, the sequence is aborted and the control is transferred there.

ALGOL 68

Works with: ALGOL 68 version Standard - except the Refinement Preprocessor is an extension
Works with: ALGOL 68G version Any - tested with release mk15-0.8b.fc9.i386

See also Exceptions to see how ALGOL 68 handles transput events.

One common use of a label in ALGOL 68 is to break out of nested loops.

<lang algol68>(

  FOR j TO 1000 DO
    FOR i TO j-1 DO
      IF random > 0.999 THEN
        printf(($"Exited when: i="g(0)", j="g(0)l$,i,j));
        done
      FI
      # etc. #
    OD
  OD;
done: EMPTY

);</lang>

Multi way jump using labels and EXIT to return result

<lang algol68>STRING medal = (

 []PROC VOID award = (gold,silver,bronze);
 award[ 1 + ENTIER (random*3)];
 gold: "Gold" EXIT
 silver: "Silver" EXIT
 bronze: "Bronze"

);

print(("Medal awarded: ",medal, new line));</lang>

Another use is to implement finite state machines

<lang algol68>STRING final state = (

 INT condition;
 PROC do something = VOID: condition := 1 + ENTIER (3 * random);
 
 state1:
    do something;
    CASE condition IN
       state 1, state 2
    OUT
       state n
    ESAC
 EXIT
 
 state 2:
    "State Two"
 EXIT
 
 state n:
    "State N"

); print(("Final state: ",final state, new line));</lang>

ALGOL 68G implements a Refinement Preprocessor to aid with top down code development

<lang algol68># example from: http://www.xs4all.nl/~jmvdveer/algol.html - GPL # determine first generation; WHILE can represent next generation DO calculate next generation;

  print next generation

OD.

determine first generation:

  INT previous := 1, current := 3.

can represent next generation:

  current <= max int - previous.

calculate next generation:

  INT new = current + previous;
  previous := current;
  current := new.

print next generation:

  printf (($lz","3z","3z","2z-d$, current,
           $xz","3z","3z","2z-d$, previous,
           $xd.n(real width - 1)d$, current / previous)).</lang>

Sample output:

Exited when: i=13, j=53
Medal awarded: Gold
Final state: State Two

             4              3 1.33333333333333
             7              4 1.75000000000000
            11              7 1.57142857142857
etc...

AutoHotkey

<lang AutoHotkey>MsgBox, calling Label1 Gosub, Label1 MsgBox, Label1 subroutine finished Goto Label2 MsgBox, calling Label2 ; this part is never reached Return

Label1:

 MsgBox, Label1 

Return

Label2:

 MsgBox, Label2 will not return to calling routine

Return</lang>

AWK

Awk has break and continue for loop control, as in C. <lang awk>$ awk 'BEGIN{for(i=1;;i++){if(i%2)continue; if(i>=10)break; print i}}' 2 4 6 8</lang>

C

goto

One common use of goto in C is to break out of nested loops. <lang c>int main() {

 int i,j;
 for (j=1; j<1000; j++) {
   for (i=0; i<j, i++) {
     if (exit_early())
       goto out;
     /* etc. */
   }
 }

out:

 return 0;

}</lang>

C++

goto

Works with: GCC version 3.3.4

<lang cpp>#include <iostream>

int main() {

LOOP:
 std::cout << "Hello, World!\n";
goto LOOP;

}</lang>

Note that "goto" may also be used in conjunction with other forms of branching.

Exceptions

Works with: GCC version 4.0.2

Exceptions are a way to give control back to a direct or indirect caller in case of an error. Note that throwing exceptions is usually very expensive, therefore they generally should only be used for exceptional situations. <lang cpp>#include <iostream>

  1. include <ostream>

void foo() {

 std::cout << "Going to throw an exception.\n";
 throw 7; // almost any object can be thrown, including ints
 std::throw << "This output will never execute.\n";

}

void bar() {

 std::cout << "Going to call foo().\n";
 foo();
 std::cout << "This will be skipped by the exception coming from foo.\n";

}

void baz() {

 try // everything thrown from inside the following code block
 {   // will be covered by the following catch clauses
   std::cout << "Going to call bar().\n";
   bar();
   std::cout << "This will be skipped by the exception coming from foo.\n";
 }
 catch(...) // a simple catch-all, but doesn't give access to the thrown exception
 {
   std::cout << "An exception occured. I'll just throw it on.\n";
   throw; // without an argument, the caught exception is re-thrown
 }
 std::cout << "This will not be executed due to the re-throw in the catch block\n";

}

void foobar() {

 try
 {
   baz();
 }
 catch(char const* s)
 {
   std::cout << "If foo had thrown a char const*, this code would be executed.\n";
   std::cout << "In that case, the thrown char const* would read " << s << ".\n";
 }
 catch(int i)
 {
   std::cout << "Caught an int, with value " << i << " (should be 7).\n";
   std::cout << "Not rethrowing the int.\n";
 }
 catch(...)
 {
   std::cout << "This catch-all doesn't get invoked because the catch(int) above\n"
             << "already took care of the exception (even if it had rethrown the\n"
             << "exception, this catch-all would not be invoked, because it's\n"
             << "only invoked for exceptions coming from the try block.\n";
 }
 std::cout << "This will be executed, since the exception was handled above, and not rethrown.\n";

}

int main() {

 try
 {
   foobar();
 }
 catch(...)
 {
   std::cout << "The main function never sees the exception, because it's completely handled\n"
             << "inside foobar(). Thus this catch-all block never gets invoked.\n";
 }

}</lang>

D

goto

<lang d>label1: writeln ("i'm in your infinite loop"); goto label1;</lang>

Exceptions

D supports standard try/catch/finally mechanisms: <lang d>void main (char[][] args) { try { if (args[1] == "throw") throw new Exception ("message"); } catch (DerivedException ex) { // we never threw a DerivedException, so this block is never called writefln ("caught derived exception %s", ex.toString); } catch (Exception ex) { writefln ("caught exception: %s", ex.toString); } catch (Object ex) { // Throwing Objects is allowed but discouraged. writefln ("caught object: %s", ex.toString); } finally { writeln ("finished (exception or none)"); } }</lang>

Scope guards

In a complex function, you might need to do cleanup in case of an exception, but it gets out of hand if there are many initialization steps that could fail. Scope guards offer a simplified syntax for try/finally.

There are three scopes you can listen for: exit, which is called unconditionally; failure, which is called if you leave the function via an exception; and success, which is called if you return from the function normally. A statement inside a scope block is only executed if execution reaches the scope block.

For instance: <lang d>void main (char[][] args) { scope (exit) writeln ("gone"); if (args[1] == "throw") throw new Exception ("message"); scope (exit) writeln ("gone, but we passed the first chance to throw an exception"); }</lang>

If the exception is thrown, then the only text that is written to the screen is "gone". If no exception is thrown, both calls to writeln occur.

scope (failure) and scope (success) work similarly.

E

E does not have goto. The only primitive flow control construct which is not a loop, conditional, or exception is escape, or ejectors.

The basic syntax is

<lang e>escape ej {

 ...body...

}</lang>

Within body variable ej then contains a one-argument function (an ejector) which, if called, immediately returns the provided value from the escape block.

This is a limited form of continuation (it cannot be used after the escape block exits).

Loop break, loop continue, and return-from-middle-of-function are all defined in terms of this basic construct.

Forth

CATCH-THROW

Some Forth implementations have goto, but not the standard. It does have an exception mechanism. <lang forth>: checked-array

 CREATE ( size -- ) DUP , CELLS ALLOT
 DOES> ( i -- a+i )
   2DUP @ 0 SWAP WITHIN IF
     SWAP 1+ CELLS +
   ELSE
     1 THROW
   THEN ;

8 checked-array myarray

safe-access ( i -- a[i] )
 ['] myarray CATCH 1 = IF ." Out of bounds!" 0 THEN ;</lang>

IDL

goto

<lang idl>test: ..some code here goto, test</lang>

(This is almost never used)

on_error

<lang idl>on_error, test</lang>

(This resumes at the label test if an error is encountered)

on_ioerror

<lang idl>on_ioerror, test</lang>

(Same as on_error, but for EOFs and read-errors and such)

break

<lang idl>break</lang>

immediately terminates the innermost current loop (or if or case etc)

continue

<lang idl>continue</lang>

immediately starts the next iteration of the current innermost loop

J

Control structures should usually [but not always] be avoided in J. J's primitives already provide iteration and selection.

For example, here's an example of a program which loops over a sequence of integers, multiplying them by two (the result is displayed on the following line): <lang j> 2 * 1 2 3 2 4 6</lang>

That said, J's control structures are documented at http://www.jsoftware.com/help/dictionary/ctrl.htm So, if you want to perform this same operation using a while loop, or a goto, you can do so. It's just... probably not a good idea.

Java

"goto" is a reserved keyword in Java; but you cannot use it. There are currently no goto statements.

Perl

Works with: Perl version 5.x

goto

Goto is typically looked down upon by most Perl programmers

<lang perl>FORK:

  1. some code

goto FORK;</lang>

Pop11

quitloop

quitloop with argument exits from nested loops:

<lang pop11>while condition1 do

  while condition2 do
     if condition3 then
        quitloop(2);
     endif;
  endwhile;

endwhile;</lang>

above quitloop(2) exits from both loops.

goto

goto l transfers control to the label l. goto may be used to exit from nested loops:

<lang pop11>while condition1 do

  while condition2 do
     if condition3 then
        goto l;
     endif;
  endwhile;

endwhile; l:;</lang>

Another use is to implement finite state machines:

<lang pop11>state1:

  DO_SOMETHING();
  if condition1 then 
     goto state1;
  elseif condition2 then
     goto state2;
  ....
  else
     goto stateN;
  endif;

state2:

  ....

... ... stateN:

  ....</lang>

Pop11 goto is a nonlocal one, so "jump out" from a chain of procedure calls:

<lang pop11>define outer();

  define inner(n);
     if n = 0 then
        goto final;
     endif;
     inner(n - 1);
  enddefine;
  inner(5);
  final:;

enddefine;</lang>

This is useful to exit early from successful recursive search, and for exception handling.

go_on

go_on is a multiway jump

<lang pop11>go_on expression to lab1, lab2, ..., labN else elselab ;</lang>

If expression has value K the above will jump to label labK, if expression is not an integer, or if it outside range from 1 to N, then control passes to label elselab. The else part may be omitted (then out of range values of expression cause an exception).

There is a more structured variant of go_on:

go_on expression to lab :

  lab 1 : statement1;
  lab 2 : statement2;
  ....

endgo_on;

where lab is a prefix chosen by the user.

return

return ends execution of current function. In simplest form it is just:

<lang pop11>return;</lang>

but it is also possible to specify one or more return values:

<lang pop11>return(val1, val2, val3);</lang>

chain

chain has effect of "tail call" but is not necessarily in tail position. More precisely inside proc1.

<lang pop11>chain proc2(x1, x2, x3);</lang>

finishes execution of proc1 and transfers control to the proc2 passing it x1, x2, and x3 as arguments. On return from proc2 control passes to caller of proc1.

Remark: Pop11 does not perform "tail call optimization", one has to explicitly use chain.

Python

Loops

Python supports break and continue to exit from a loop early or short circuit the rest of a loop's body and "continue" on to the next loop iteration. <lang python># Search for an odd factor of a using brute force: for i in range(n):

   if (n%2) == 0:
       continue
   if (n%i) == 0:
       result = i
       break

else:

   result = None
   print "No odd factors found"</lang>

In addition, as shown in the foregoing example, Python loops support an else: suite which can be used to handle cases when the loop was intended to search for something, where the code would break out of the loop upon finding its target. In that situation the else: suite can be used to handle the failure. (In most other languages one is forced to use a "sentinel value" or a special flag variable ... typically set to "False" before the loop and conditionally set to "True" within the loop to handle situations for which the Python else: on loops is intended).

Exceptions

A Python exception is simply any subclass of the built-in BaseException class, or any of its descendents. User defined exception classes are normally descendents of the Exception class (which is, itself, a subclass of BaseException). To "throw" any exception (user defined or otherwise) one uses the raise statement. To capture exceptions one must enclose the code in a try: ... except...: block. Any exception listed in an except block will catch all subclasses of that exception. For example ZeroDivisionError is derived from ArithmeticError. Thus an exception clause for ArithmeticError would catch a ZeroDivisionError (or any other ArithmeticError).

As a consequence of this one must arrange the order of exception clauses such that the more specific exceptions are listed (caught) before their more general base exceptions. Only the first matching exception clause will be executed. An except clause which lists no exceptions will catch all possible exceptions. (This is usually considered to be very poor programming practice because it can hide unintended coding errors).

An exception can be re-raised by simply calling the raise statement without any arguments (from within any exception handler). Thus a function can catch an exception, attempt to deal with it, then, if necessary, throw it it back to the next layer out in a given call stack. Uncaught exceptions will be handled by the interpreter by terminating the program and printing an error message and stack trace.

A custom Exception class is normally declared with the pass statement as no methods of the parent class are over-ridden, no additional functionality is defined and no attributes need be set. Example:

<lang python>class MyException(Exception): pass</lang>

One normally would choose the most similar existing class. For example if MyException was going to be raised for some situation involving an invalid value it might be better to make it a subclass of ValueError; if it was somehow related to issues with inappropriate objects being passed around then one might make it a subclass of TypeError.

In large projects it's common to create an custom application base exception and to have all or most custom exceptions within that application or framework derive therefrom.

To create a "virtual base class" (one which is not intended to be directly instantiated, but exists solely to provide an inheritance to it's derived classes) one normally defines the requisite methods to raise "NotImplementedError" like so:

<lang python>class MyVirtual(object):

   def __init__(self):
       raise NotImplementedError</lang>

It then becomes necessary for any descendants of this class to over-ride the __init__() method. Any attempt to instantiate a "MyVirtual" object directly will raise an exception.

Case 1 - Try, Except

<lang python>try:

   temp = 0/0
  1. 'except' catches any errors that may have been raised between the code of 'try' and 'except'

except: # Note: catch all handler ... NOT RECOMMENDED

   print "An error occurred."
  1. Output : "An error occurred"</lang>

Case 2 - Try, Except

<lang python>try:

   temp = 0/0
  1. here, 'except' catches a specific type of error raised within the try block.

except ZeroDivisionError:

   print "You've divided by zero!"
  1. Output : "You've divided by zero!"</lang>

Case 3 - Try, Except, Finally

<lang python>try:

   temp = 0/0

except:

   print "An error occurred."
  1. here, 'finally' executes when the try - except block ends, regardless of whether an error was raised or not
  2. useful in areas such as closing opened file streams in the try block whether they were successfully opened or not

finally:

   print "End of 'try' block..."
  1. Output :
  2. An error occurred
  3. End of 'try' block...</lang>

Note: Prior to version 2.5 a try: statement could contain either series of except: clauses or a finally: clause but not both. It was thus necessary to nest the exception handling in an enclosing try:...finally: loop like so:

<lang python>try:

   try:
       pass
   except (MyException1, MyOtherException):
       pass
   except SomeOtherException:

finally:

   do_some_cleanup() # run in any case, whether any exceptions were thrown or not</lang> 

Case 4 - Try, Except, Else

<lang python>try:

   temp = 1/1 # not a division by zero error

except ZeroDivisionError: # so... it is not caught

   print "You've divided by zero."
  1. here, 'else' executes when no exceptions are caught...

else:

   print "No apparent error occurred."
  1. Output :
  2. No apparent error occurred.</lang>

Case 5 - Try, Except, break, continue

<lang python>i = 0 while 1: # infinite loop

   try:
      temp2 = 0/i # will raise a ZeroDivisionError first.
      temp = math.sqrt(i)
      
      break # 'break' will break out of the while loop
   except ValueError: #
       print "Imaginary Number! Breaking out of loop"
       break # 'break' out of while loop
   except ZeroDivisionError:
       print "You've divided by zero. Decrementing i and continuing..."
       i-=1 # we decrement i.
       # we 'continue', everything within the try - except block will be executed again, 
       # this time however, ZeroDivisionError would not be raised again.
       continue # Note that removing it, replacing it with 'pass' would perform the equivalent
                # see below for a better example
  1. Output :
  2. You've divided by zero. Decrementing i and continuing...
  3. Imaginary Number! Breaking out of loop</lang>

Case 6 - Creating your own custom exceptions, raise

<lang python># Let's call our custom error "StupidError"; it inherits from the Exception class

class StupidError(Exception): pass

  1. Try it out.

try:

   raise StupidError("Segfault") # here, we manually 'raise' the error within the try block

except StupidError, details: # 'details' is the StupidError object we create in the try block.

   print 'Something stupid occurred:', details # so we access the value we had stored for it...
       
  1. Output :
  2. Something stupid occurred: Segfault</lang>

Case 7 - continue, else in "for" loop

<lang python> i = 101

   for i in range(4): # loop 4 times
       print "I will always be seen."
       if (i % 2) == 0:
           continue # continue goes back to the loop beginning for a new iteration.
       print "I'll only be seen every other time."
   else:
       print "Loop done"
   
   # Output:
   # I will always be seen.
   # I will always be seen.
   # I'll only be seen every other time.
   # I will always be seen.
   # I will always be seen.
   # I'll only be seen every other time.
   # Loop done
       

if(__name__ == "__main__"):

   main()</lang>

The "with" statement

Works with: Python version 2.6

See [PEP 0343, The "with" statement]

<lang python>class Quitting(Exception): pass max = 10 with open("some_file") as myfile:

   exit_counter = 0
   for line in myfile:
       exit_counter += 1
       if exit_counter > max:
           raise Quitting 
       print line,</lang>

The with statement allows classes to encapsulate "final" (clean-up) code which will automatically be executed regardless of exceptions that occur when working "with" these objects. Thus, for the foregoing example, the file will be closed regardless of whether it's more than 10 lines long. Many built-in and standard library classes have "context managers" which facilitate their use in with: code. In addition it's possible to define special __enter__() and __exit__() methods in one's own classes which will be implicitly called by the interpreter when an object is used within a with: statement.

Use cases for with: enabled objects include automated/guaranteed closing of files, release of threading lock objects, commit or rollback of database transactions, and save/restore of any desired state (such as terminal settings when using the curses module, the precision settings when using the Decimal module, or even saving and restoring sys.stdout for temporary redirection). It is a feature that seems to be unique to Python.

Yield expressions

Works with: Python version 2.5

See [PEP 0342, Coroutines via Enhanced Generators]

>>> value = 1
>>> echo = lambda: (yield value)
>>> for i in echo():
...   print i
...
1

Ruby

return

Return from the currently executing method to the caller.

loop control

Ruby's loop control statements are: break, next, redo and retry. Break and next are obvious. Redo and retry both restart the current loop iteration, but retry first reevaluates the condition. They can control while, until, for loops and iterators.

exceptions

Use raise to throw an exception. You catch exceptions in the rescue clause of a begin...end block. <lang ruby>begin

 # some code that may raise an exception

rescue ExceptionClassA => a

 # handle code

rescue ExceptionClassB, ExceptionClassC => b_or_c

 # handle ...

rescue

 # handle all other exceptions

else

 # when no exception occurred, execute this code

ensure

 # execute this code always

end</lang> There is also a rescue modifier (example from the Pickaxe book): <lang ruby>values = ["1", "2.3", /pattern/] result = values.map {|v| Integer(v) rescue Float(v) rescue String(v)}

  1. => [1, 2.3, "(?-mix:pattern)"]</lang>

catch and throw

break will only break out of a single level of loop. You can surround code in a catch block, and within the block you can throw a string or symbol to jump out to the end of the catch block (Ruby's GOTO, I suppose): <lang ruby>def some_method

 # ...
 if some_condition
   throw :get_me_out_of_here
 end
 # ...

end

catch :get_me_out_of_here do

 for ...
   for ...
     some_method
   end
 end

end

puts "continuing after catching the throw"</lang>

yield

yield passes control from the currently executing method to its code block.

Tcl

after

The after facility can be used to execute some code at some future time asynchronously, like this

<lang tcl>after 1000 {myroutine x}</lang>

which will call "myroutine" with parameter "x" 1000ms from 'now'; no matter what other code might be running at the time (i.e. "after" schedules the execution, then returns and continues program flow with the following code).

The scheduled task can be removed from the scheduler for example with

<lang tcl>after cancel myroutine</lang>

(other ways are possible).

The correct way to schedule some regularly recurring task in TCL is to incorporate a self-scheduling at the end of the routine. For example the following will produce a clock whose display is updated once a second:

<lang tcl>package require Tk proc update {} {

   .clockface configure -text [clock format [clock seconds]]
   after 1000 update ; # call yourself in a second

}

  1. now just create the 'clockface' and call ;update' once:

pack [label .clockface] update</lang>

loop control

Tcl has the break command to abort the current loop (for/foreach/while) and the continue command to skip to the next loop iteration.

exception

Tcl's catch command can be used to provide a basic exception-handling mechanism: <lang tcl>if {[catch { ... code that might give error ... } result]} {

   puts "Error was $result"

} else {

   ... process $result ...

}</lang> Tcl 8.6 also has a trytrapfinally structure for more complex exception handling. <lang tcl>try {

   # Just a silly example...
   set f [open $filename]
   expr 1/0
   string length [read $f]

} trap {ARITH DIVZERO} {} {

   puts "divided by zero"

} finally {

   close $f

}</lang>

custom control structures

A novel aspect of Tcl is that it's relatively easy to create new control structures (more detail at http://wiki.tcl.tk/685). For example, this example defines a command to perform some operation for each line of an input file: <lang tcl>proc forfilelines {linevar filename code} {

   upvar $linevar line ; # connect local variable line to caller's variable
   set filechan [open $filename]
   while {[gets $filechan line] != -1} {
     uplevel 1 $code   ; # Run supplied code in caller's scope
   }
   close $filechan

}</lang> Now we can use it to print the length of each line of file "mydata.txt": <lang tcl>forfilelines myline mydata.txt {

   puts [string length $myline]

}</lang>

Visual Basic .NET

Goto

This skips the line that changes the value of x to 5.

<lang vbnet> Sub bar2()

     Dim x = 0
     GoTo label
     x = 5

label:

     Console.WriteLine(x)
 End Sub</lang>

On Error Goto

This brances in the event of an error. Usually there is an Exit (Sub|Function) to seperate the normal code from the error handling code

<lang vbnet> Sub foo()

      On Error GoTo label
      'do something dangerous
      Exit Sub

label:

      Console.WriteLine("Operation Failed")
  End Sub</lang>

This style of code is rarely used.

On Error Resume Next

This performs a sequence of actions. If any action fails, the exception is discarded and next operation is performed.

<lang vbnet>Sub foo2()

   On Error Resume Next
   Operation1()
   Operation2()
   Operation3()
   Operation4()

End Sub</lang>

This style of code is rarely used.

Return / Exit Sub

This shows the classical and modern syntax for exiting a sub routine early.

<lang vbnet>Sub Foo1()

   If Not WorkNeeded() Then Exit Sub
   DoWork()

End Sub

Sub Foo2()

   If Not WorkNeeded() Then Return
   DoWork()

End Sub</lang>

Return value / Exit Function

This shows the classical and modern syntax for exiting a function early. There is an implied variable with the same name as the function. This variable is write-only.

<lang vbnet>Function Foo3()

   Foo3 = CalculateValue()
   If Not MoreWorkNeeded() Then Exit Function
   Foo3 = CalculateAnotherValue()

End Function

Function Foo4()

   Dim result = CalculateValue()
   If Not MoreWorkNeeded() Then Return result
   Return CalculateAnotherValue()

End Function</lang>