- while( my-guitar-gently-weeps ) ♭The Beatles 1968 Armed with the
08a-FirstNegative.ox 1: #include "oxstd.h" 2: 3: const decl vec = <0.12; 2.3; -6.5>; 4: 5: main() { 6: decl fneg; 7: fneg = 0.0; //no negative found yet. 8: if (vec[0]<0.0) 9: fneg = vec[0]; 10: else if (vec[1]<0.0) 11: fneg = vec[1]; 12: else if (vec[2]<0.0) 13: fneg = vec[2]; 14: if (fneg<0.0) 15: println("first negative value =",feg); 16: else 17: println("no negative values in vec"); 18: }
This is a sequence of «initialize condition for first pass» while( «condition» ) «statement»
The "initialize condition for first pass" is not part of the syntax, but it is important for the logic of a while loop. Your program has to make sure that the condition to be checked is correct the first time it is checked. Then the conditional has to somehow be updated inside the "body" of the while loop.
Remember that a block of statements inside curly brackets is a statement. So the while loop can repeat as many individual statements as you want. Once the condition is not true the program will skip below the repeated statement and continue.
fneg = 0.0; i = 0; while( (fneg==0.0) && (i<3) ) { if (vec[i]<0.0) fneg = vec[i]; ++i; } if (fneg<0.0) println("first negative value =",feg); else println("no negative values in vec");
i = 0; while( (i<3) && (vec[i]≥0.0) ) ++i; if (i<3) println("first negative value =",vec[i]); else println("no negative values in vec");
n = rows(vec); i = 0; while( (i<n) && (vec[i]≥0.0) ) ++i; if (i<n) println("first negative value =",vec[i]); else println("no negative values in vec");
- for ( the-nights ; I-can't ; remember ) Many loops in a program amount to the same basic logic: start with the first case, do something to it; move on to the next case and do the same thing to it; repeat until all the cases are processed. That is a little different than the while loop above because it stops processing the cases (the elements of the vector) when a negative value is encountered. As an example that process all the cases, suppose we want deal with an
decl stud, names; names = {"Adele","Beyonce","Rhianna"}; stud = 0; while(stud<3) { println(stud,". ", names[stud]); ++stud; }
This loop uses the increment operator for ( «initialize» ; «condition» ; «incremement» ) «statement» ↓ ↓ ↓ ↓ for ( stud = 0 ; stud<3 ; ++stud ) println(stud,". ", names[stud]);
Notice that the first part initializes a loop counter, in this case - The first thing that happens in a
for loop
is setting of the loop counter. It must be initialized before entering the loop. And it is important that nothing inside the loop uses the loop counter for any other purpose, say to store the result of adding two numbers which would wipe out the current value of the counter. - Next, the condition for doing another iteration of the loop is tested. In the standard for loop this is a test whether the current value of the counter is still less than the number of cases to process. If so the body of the loop is entered. Otherwise the for loop is finished.
- If the condition is true the statement (which can be a block of statements) is executed. This is the body of the loop.
- After that is done, the increment is done, which means to update the loop counter. In the simplest case 1 is added to the counter. Then the for loop goes back to step 1 and checks the condition again.
- Once the condition is false the for loop ends and the program will proceed to the next statement below the body of the loop.
- What's your vector, Victor? Most of the logical actions that computer hardware can carry out is captured by if and while statements. We can visualize what these structures do using flowchart diagrams. The enormous (but not boundless) power and flexibility of computation come from arranging these logical steps so that they implement an algorithm. Humans do pretty well with visual representations such as flowcharts. Once the human believes the flowchart captures the desired algorithm they can convert the flowchart elements into programming structures in a computer language like Ox. Then other software can take over to convert the program into a machine instructions that execute the algorithm.
- foreach
foreach ( «local-variable» in «list-thing» ) «statement »
Here is an earlier example re-written with decl singer, names; names = {"Adele","Beyonce","Celine"}; foreach (singer in names) println(singer);
With output:Adele Beyonce Celine
Notice there is no need for a loop counter variable here. The - Do I Do♭Stevie Wonder 1982 The
- Break on Through to the Other Side♭The Doors 1967 A
for(i=0;i<N;++i) { for(i=0;i<N;++i) { … … if (sayhi) if (!sayhi) print("hi"); continue; print("hi"); } }
It's not that i=0; negx = FALSE; while (i<N && !negx) { for(i=0;i<N;++i) { … … negx = x < 0; if (x<0) break; ++i; } }
if()
statement your program can respond dynamically to results that were not known until the program was executing. So the plans your program can implement are now more interesting. But very simple calculations are still tedious to program.
For example, suppose there is a vector of 3 numbers and you want to find the first element that is negative. So if the vector is $\l(\matrix{0.12&2.3&-6.5}\r)$ we want the program to print out -6.5 since the previous values were positive. And if there are no negative values we would want to know that.
Not knowing any syntax except if-then-else
your code might look like this:
if
statements of the same form with only the element of vec
being checked changing each time. We want to keep checking while a negative value has not been encountered. It would be more elegant and more flexible if the calculation could simply repeat one statement changing the index each time.
Language structures (syntax) that supports the repetition of one or more statements are called iterative statement. There are several different standard loop structures. The simplest version to explain is usually called a while loop, which has a flowchart figure:
The idea of a repeated if statement was introduced earlier in the section on hardware. That's because one machine instruction is to jump or go to a different location in memory and start executing code there. That location can be "upstream" in the flow of instructions from where the jump occurs. The while loop is a way to ensure that the jump goes back to the right place and not accidentally somewhere else.
The flowchart for the while loop corresponds to the while()
statement in Ox. It's form is
To implement the nested if
statements as a while
loop we need a new variable, the index into vec
. The index contains the current element to look it. It will start at 0 then 1 then 2, but only if necessary (if a negative value has not been found yet).
Implicit Types
A long tradition in computing is a loop index to be named i
or j
or some other letter like that, but not x
or y
. One reason: back in the 1950s variables in FORTRAN that started with the letters i, j, k, l, m and n were implicity integers
and could be used as loop counters or array indices. Variables that started with other letters like x
were implicitly real values.
With a while()
statement we can rethink the loop in many ways. If we get to the end of the vector with no negatives the index i
will equal 3, because the while loop will increment i beyond the biggest index in vec
. This means the final value of i
can be used to avoid the need for fneg
:
It would also be much more useful if the while loop could be used no matter what length vec
is. That is possible using the built-in rows()
function in Ox which returns the number of rows of a matrix:
oxarray
(a list). For example, a voice teacher has three students in their class and (for some strange reason uses Ox). They want to print out the class roster. Using a while()
statement it might look like:
++
discussed earlier. This kind of loop happens all the time in code. And things can go wrong. One of the practical problems is the following: if many statements are in the body of the loop (the repeated instructions) then the increment part may be a long way from the while()
part. That might means it is forgotten or misplaced. It would be clearer to the programmer if the increment statement (go to the next student) could stay close to the top of the loop where the condition on students is checked.
Because this kind of loop is so common a special loop exists in all languages to simplify it. Here is the general syntax of a Ox for
loop and the translation of the while
loop into it.
stud
. The second part is the condition to check on each pass of the loop which corresponds to the condition in a while()
loope. The first time this condition is FALSE the loop ends like a while()
loop ends. The third part is what would appear at the bottom of a while loop. It increments or updates the condition which will be checked at the topof the loop.
The while
loop can do anything a for
can do, but a for
loop puts all the important information about the looping process in one place. This makes the for()
code easier to read that while()
. (Further, a for()
loop can be coded so that it can do anything a while()
can do, but doing so might make the for()
loop convoluted.
As usual, Python syntax is simpler than Ox, but
while
is the same. The for
loop in Python is more like the foreach
loop in Ox discussed later. Ox's for loop syntax comes directly from C syntax.Explanation of a typical for-loop
Here is a simple example. Victor is writing a program that involves a vector $v$. He needs to know how many elements of the vector are positive. In other words, he must count the number of times a condition is true. Mathematically, Victor wants to implement: $$S = \sum_{i=0}^{N-1} I\{v_i > 0\},\tag{VP}\label{VP}$$ and $I{d}$ is the indicator function that takes on the value 1 if the condition is true and 0 if false. For example, if $v=\l(\matrix{5&-33&0}\r)$ the $S=1$ because one element is positive. The indicator can be handled by an if statement. The summation over indicator values can be handled by a for-loop. A key thing about the summation is the indicator function appears inside the loop. As discussed above, variables that a loop modifies must be initialized before the loop starts. In the mathematical expression for $P$ we just see a simple assignment, but when the summation is done step by step the count has to start at 0 before the loop begins. With that we can write a flowchart for Victor's requirement:
In the flowchart the length of the vector $N$ is shown as rows(V)
like Ox. The art and science of mathematical computing is placing elements such as if and for in the right order in order to implement the desired algorithm. To see this, consider a different expression:
$$P = I\{ \sum_{i=0}^{N-1} v_i > 0\}.\tag{VS}\label{VS}$$
All Victor wants to know is whether the sum is positive or not and have $P$ indicate that. So for the $v$ $P=0$ because $5-33+0 < 0.$ The elements of \eqref{VP} and \eqref{VS} are the same, but the loop is now inside the condition. A flowchart that would do the check for him is below.
Thewhile()
andfor()
loop structures are essential parts of Ox and any programming language. The sections below discuss useful but not necessary features of Ox that allow you to specialize your loops even more.
while()
and for()
are the basic iterative statements, but there are two others in Ox that can be useful. Like the for
loop they make it easier to write reliable code than relying solely on basic if()
and while()
. But they are not necessary in the sense that anything you do with them can be done with just if()
and while()
.
The foreach()
statement can be used to loop over all elements in a matrix, array or string. The simple form is:
foreach
.
foreach()
structure goes through the items after in
. In this case it is an array but it could be a vector or a matrix. And it then assigns the values in the list to the variable before in
before executing the statement (or statement block). Notice that in the print statement there is no way to know where we are on the list because there is no loop counter. So as written it cannot print 0. Adele
like the earlier code. There are other forms of foreach()
that do create and loop counter for you to use. Look at the Ox syntax reference guide for more examples.
do «statement» while(«condition»)
statement executes the statement (or statement block inside { }
), then checks the condition and will repeat the statement if it is TRUE. It keeps doing this until the condition is false. Notice that the while()
appears at the end (or at the bottom of the loop) so this is not the same at all as the simple while()
loop. (Other languages use different words and this might avoid some confusion. For example Pascal uses repeat … until ()
.
As with other loops, you could get a while()
loop to do the same thing that a do … while()
loop does. The difference is that do-while
will execute the statement inside once for sure. A plain while()
loop checks the condition at the top a while loop might not execute the inside statement at all. So a while()
loop is called a zero-pass loop, meaning it potentially makes no pass of the inside statement. A do … while()
loop is a one-pass loop because it executes the body of the loop at least once.
One reason for using a one-pass loop is it can avoid using same code in two places, once before the while loop so that a condition can be checked and then inside the loop to be repeated. With a do … while()
the inside is done before the first condition is checked so it does not have to be copied.
continue
statement may only appear within a loop (any kind of loop is fine). If your program gets to a continue
statement it is as if the rest of the statements inside the loop are skipped and the program goes back to the check for continuing the loop immediately. Suppose you want to process $N$ things and (strangely) print "hi" each time, but only if the variable sayhi
is TRUE.
Here is how to program this two ways: with if()
and with continue
:
continue
let's you do something you can't do with if
. Its value is that it may make your code simpler or more intuitive to you or other humans than if you rely on the bare essential structures.
Similarly, a break
statement also goes inside loops. If it is executed the loop ends immediately. So suppose you want to process $N$ things but if x
becomes negative you need to stop immediately. and go below the loop. Here are while and for loops that do the same thing:
Exercises
while()
loop to compute the sum value of a vector then print it out.
09a-Sum.ox 1: #include2: 3: main() { 4: decl v, i, S; 5: v = < 3;2;6;-1;5>; 6: // initialize 7: 8: while ( /* condition */ ) { 9: //body of loop 10: 11: 12: // increment 13: } 14: 15: // continue 16: println("S = ",S); 17: }
while()
loop to compute the largest (max) value in a vector then print it out. Use this logic: If the vector only has one element then its first (and only) value is the largest. Then if it has more than 1 element, check each element against the current max. If it is bigger it becomes the max.while()
loop to compute the average value of a vector. Re-program it to use a for()
loop instead.while()
loop to compute the largest value in a vector to use a for()
loop instead.for loop
to create their sum.