Flow Control

From Jonathan Gardner's Tech Wiki
Jump to: navigation, search

Introduction

Flow control is how programs are written so that certain parts of the program are run at different times according to circumstances.

GOTO / JMP

The most basic form of flow control is the JMP or GOTO. This directs the program to resume execution at some other point.

Note that this really isn't flow control---it is simply directing the program to resume somewhere else, under all circumstances. However, it does allow for some basic looping.

Most modern programming languages don't allow JMP or GOTO. Some holdovers from an earlier programming era still have them, although they are heavily discouraged nowadays.

Writing code in assembly requires GOTO / JMP. It's simply impossible to program otherwise.

IF / JNE / JGE

The next most basic code element is the "if" condition, sometimes represented with the assembly codes "JNE" (jump if not equal) or "JGE" (jump if greater than or equal).

This directs the program to continue execution somewhere else (like a GOTO or JMP) if some condition is met.

In Python:

if x == 0:
    y = 5

This sets "y" to 5 if "x" is equal to 0.

IF / ELSE

Adding to "if" is the "else". This code is executed if the "if" condition is false.

In Python:

if x == 0:
    y = 5
else:
    y = 6

This sets "y" to 5 if "x" is 0. Otherwise, "y" is set to 6.

These ultimately get compiled into instructions that look like this.

CMP x 0
JNE "NOT_EQUAL"
SET y 5
JMP "CONTINUE"

NOT_EQUAL:
SET y 6
CONTINUE:
...

If you want to chain a bunch of "if" clauses to be tested one after another, you'll need an "else if" clause. These are attempted one after the other until one is found to be true.

Some languages provide a "switch" statement. This allows you to run a bunch of "if x == y" clauses one after the other, where x doesn't change, but y varies. Some programming languages optimize this check so that only the correct "y" is tested.

Subroutines / Functions

The next bit of flow control is the calling of functions. The way it works is this.

When you invoke a function, you start executing the function body with the parameters set to the arguments to the function.

When the function completes, or when the return statement is executed, then execution continues where the function call was made, with the function call evaluating to the returned value.

This is, obviously, extraordinarily useful. So useful, in fact, that languages like Lisp use it for EVERYTHING, including all other forms of flow control.

WHILE Loops

The next form of flow control is the "while" loop. This executes the body of the loop as long as the while condition is true.

In Python:

while x == 5:
    ...

The body may contain "break" or "continue" statements. "break" statements will cease the iteration immediately, and continue after the loop. "continue" statements cease this iteration, and retries the while condition to see if another iteration should be executed.

"while" loops are pretty useful, although I don't use them very often, favoring "for" loops instead.

Sometimes, you will see something like:

while True:
    ...

This is known as an "infinite loop". The body may contain "break" statements, but don't be surprised if you see one without any "break" statements. This indicates that the loop continues until the program is stopped.

FOR loops

In the early days, "for" loops had three clauses.

  • The initial clause.
  • The conditional clause.
  • The continue clause.

The initial clause is executed before the first iteration.

The conditional clause is run before each iteration, including the first. If it evaluates to false, the "for" loop is finished.

The continue clause is executed after each iteration completes.

Typically, these are used to iterate through a list of things, although the "foreach" loop is much better suited for this.

"break" and "continue" are also allowed in "for" loops. In this case, "break" means the same as in a while loop, instantly exiting the loop. However, "continue" means to execute the continue clause, then test the conditional clause to see if the next iteration should be run.

FOREACH loops

"for" loops are almost always used exclusively to iterate through a sequence of data. The data may or may not be represented as a list. It could also be a generated list of values. However, there is always the danger of miscalculating the various clauses in the "for" loop. Because of this, the "foreach" loop was introduced.

The "foreach" loop iterates through a sequence, setting the iterator variable to the value of the current element. It will stop after it has exhausted all the items, or when the "break" statement is executed. The "continue" statement moves to the next item in the list.

Python does not have a "for" loop like most other languages. Instead, its "for" loop is actually a "foreach" loop, iterating through a sequence of values.

Try Block

The try block is a relatively new concept that allows flow control to be manipulated based on exceptions.

There are, generally, four parts to a full try block.

  • The try code itself.
  • The "catch" or exception clauses.
  • The "finally" clause.
  • The "else" clause.

The try code is executed, until an exception is thrown.

If an exception is thrown, then the matching "catch" or exception clause is executed. (If an exception is thrown here, the surrounding try block would have to catch it, since this is no longer within the try code.)

If no exception is thrown, then after the try code completes, the "else" clause is executed.

Whether or not an exception is thrown, even if an exception is thrown from one of the subsequent clauses, the "finally" clause is executed before the exception is passed up or the statement completes.

Not all languages offer all four clauses. Usually, only a few of them are available. Python, however, now offers all four.