F Sharp Programming/Control Flow

In all programming languages, control flow refers to the decisions made in code that affect the order in which statements are executed in an application. F#'s imperative control flow elements are similar to those encountered in other languages.

Imperative Programming in a Nutshell
Most programmers coming from a C#, Java, or C++ background are familiar with an imperative style of programming which uses loops, mutable data, and functions with side-effects in applications. While F# primarily encourages the use of a functional programming style, it has constructs which allow programmers to write code in a more imperative style as well. Imperative programming can be useful in the following situations:


 * Interacting with many objects in the .NET Framework, most of which are inherently imperative.
 * Interacting with components that depend heavily on side-effects, such as GUIs, I/O, and sockets.
 * Scripting and prototyping snippets of code.
 * Initializing complex data structures.
 * Optimizing blocks of code where an imperative version of an algorithm is more efficient than the functional version.

Decisions
F#'s  construct has already been seen earlier in this book, but to introduce it more formally, the   construct has the following syntaxes:

Like all F# blocks, the scope of an  statement extends to any code indented under it. For example:

This program prints: condition = true: inside the 'if' outside the 'if' block

outside the 'if' block

Working With Conditions
F# has three boolean operators:

The  and   operators are short-circuited, meaning the CLR will perform the minimum evaluation necessary to determine whether the condition will succeed or fail. For example, if the left side of an  evaluates to , then there is no need to evaluate the right side; likewise, if the left side of a   evaluates to  , then there is no need to evaluate the right side of the expression.

Here is a demonstration of short-circuiting in F#: The  and   methods return   and   respectively, but they also have a side-effect of printing a message to the console whenever the functions are evaluated.

This program outputs the following: Always true Always false alwaysTrue && alwaysFalse: false --- Always false alwaysFalse && alwaysTrue: false --- Always true alwaysTrue || alwaysFalse: true --- Always false Always true alwaysFalse || alwaysTrue: true ---

As you can see above, the expression  evaluates both sides of the expression. only evaluates the left side of the expression; since the left side returns, its unnecessary to evaluate the right side.

Loops Over Ranges
loops are traditionally used to iterate over a well-defined integer range. The syntax of a  loop is defined as:

Here's a trivial program which prints out the numbers 1 - 10:

This program outputs: i: 1 i: 2 i: 3 i: 4 i: 5 i: 6 i: 7 i: 8 i: 9 i: 10

This code takes input from the user to compute an average:

This program outputs: This program averages numbers input by the user. How many numbers do you want to add? 3 Input #1: 100 Input #2: 90 Input #3: 50 Average: 80

Loops Over Collections and Sequences
Its often convenient to iterate over collections of items using the syntax:

For example, we can print out a shopping list in fsi:

Loops
As the name suggests,  loops will repeat a block of code indefinitely while a particular condition is true. The syntax of a  loop is defined as follows:

We use a while loop when we don't know how many times to execute a block of code. For example, lets say we wanted the user to guess a password to a secret area; the user could get the password right on the first try, or the user could try millions of passwords, we just don't know. Here is a short program that requires a user to guess a password correctly in at most 3 attempts:

This program outputs the following: What's the password? kitty What's the password? monkey You got the password right!