Scilab Bag Of Tricks: The Scilab-2.5 IAQ (Infrequently Asked Questions) | ||
---|---|---|

Prev | Chapter 3. Programming Style | Next |

Though not recognized as that by all programmers the flow control structures themselves are first class indicators of the codes workings. We consider three important cases here.

`while`vs.`for`,`if`vs.`select`, andstrict block structure vs. premature return.

Expressed in words a `for` loop tells us:

We know exactly how many iterations we shall need before we start looping.

Nothing in the loop body will change this.

Whereas the `while` loop says:

We must check whether we should loop at all, and

we have to re-check after each iteration whether we need another round-trip.

Corollary: The termination condition of a `while`
must be influenced in the loop's body.

Compare the next to code snippets, the first calculating the average of a vector of numbers, the second searching zeroes of a given function.

values = [ 1.0 2.0 3.0 4.0 5.0 ]; average = 0; n = size(values, 'c'); // line 3 for i = 1:n average = average + values(i) end; average = average / n

Form line 3 on, we know the number of iterations,
`n`; from the problem we know that nothing will
change that. Thus a `for`-loop is adequate.

deff('[y, dy] = fun(x)', .. 'y = -0.5 + 1.0 / (1.0 + x^2), .. dy = -2.0 * x / (y + 0.5)^2'); x0 = 0.76; [y, dy] = fun(x0); while abs(y) > sqrt(%eps) x = y / dy - x0; x0 = x; [y, dy] = fun(x) end;

Assuming that the function `fun` and the start
guess `x0` is given by the user, we do not know
how many loops it will take for Newton's algorithm to converge, if
it does converge at all. (In the example it does.) Here, the
`while`-loop expresses this lack of a-priori
knowledge.

The relationship between `if` and
`select` bears similarity with
`while` and `for` respectively.
In a `select` clause the different cases are
known – and spelled out explicitely – before the
thread of control enters the construct. There is a one to one
relationship between the states of the selecting expression and
the `case` branch taken. The
`else` branch in a `select`
works exactly as the `else` in an
`if`.

**Example 3-2. Function fibonacci**

function f = fibonacci(n) // return n-th Fibonacci number select n case 0 then f = 1 case 1 then f = 1 else f = fibonacci(n - 1) + fibonacci(n - 2) end

The `select`ing expression is not restricted to
scalars. For example, vectors work too:

**Example 3-3. Function shape4**

function s = shape4(m) // classify a 2x2 matrix according to its shape select abs(m) <= %eps case [%t %t; .. %t %t] then s = "empty" case [%t %f; .. %f %t] then s = "diagonal" case [%f %f; .. %t %f] then s = "upper triangular" case [%t %t; .. %f %t] then s = "lower triangular" case [%f %f; .. %f %f] then s = "full" else s = "general" end

An `if` clause is more flexible than a
`select` clause, but at the price of being less
expressive. Whenever a whole range of values has to be covered
the `if` clause is the only way to go.

The paradigm of structured programming is: "Every block has one and only one entry point." That's it! Nothing is said about the number of exit points. The purists often misinterpret the paradigm, demanding a single exit point, too. We prefer our freedom and choose whatever we find adequate to the problem.

Here are two different implementations of an algorithm calculating the factorial of a given integral number.

function y = fact_block(x) // faculty of x // block-structured version select x case 0 then y = 1 case 1 then y = 1 else y = x * fact(x - 1) end

The two special cases `0`, and
`1` are tested separately and the general case is
handled in the `else` branch.

function y = fact_early_ret(x) // faculty of x // early-return version if x >= 0 && x <= 1 then y = 1 return end y = x * fact(x - 1)

This version immediately returns after having treated the special cases, leaving the general case to the "rest" of the function. In this very short function the advantages of the early return are not striking, however they are if there are many special cases to be handled. The "rest" of the function can then concentrate on the core of the problem without being obscured by deeply nested conditionals.