Algorithmic Composition
Chapter 10 Functional Programming
12.1 The loop Command with a for-below Clause
Chapter 12 Iteration
Iteration in programming means repeated evaluation. In SAL, iteration is accomplished through loops. Loops evaluate a set of expressions over and over again. A loop should terminate after a specified number of repetitions or when a condition is met. SAL has several iterative forms, including a loop command with many variations. This chapter will show how to solve many of the same problems presented in Chapter 11, only using iteration instead of recursion, so the reader can easily compare recursive and iterative forms.
12.1 The
loopCommand with a
for-belowClause
The most general iterative form in SAL is the loop command, which like a begin-end block organizes a set of commands, but unlike begin-end, the commands are repeated. Loop commands can in-clude clauses that create, initialize, and update local variables for each repetition. Loop commands can also include clauses that stop the repetition when certain conditions are met. For now, we will start with a simple form of loop, using a for clause to control the number of iterations.
The template for this simple form of loop is loop
for counter below count-expression commands
end
This loop is evaluated as follows: First, counter (a variable) is ini-tialized to zero, and count-expression is evaluated to obtain a number we will call limit. If counter is less than limit, commands (any num-ber of commands) are evaluated. Then counter is incremented by 1, and the loop repeats by again comparing counter to limit and evalu-ating commands again. When counter reaches or exceeds limit, the loop ends.
In Example 12.1.1, we use a loop to increment the counter count. As we enter the loop, the variable count starts counting at 0. We enter the body of the loop and print the value of count. count is then incremented (to 1). Because the new value of count is less than the count expression (4), the body of the loop is executed again. The it-erative process stops when count equals 4. The number of iterations
12.1 The loop Command with a for-below Clause 149 is given by the limit (4), and the values of the count range from 0 to limit - 1.
Example 12.1.1: A simple loop SAL> loop
for count below 4 display “loop”, count end
loop : COUNT = 0 loop : COUNT = 1 loop : COUNT = 2 loop : COUNT = 3
In Example 12.1.2, we define a function make-a-chromatic-lick using iteration rather than recursion. The purpose of the function is to create a list that generates a specified number of half steps from a starting key number. The begin statement first initializes the variable the-list (to nil). The notes we generate will be collected into the-list. The body of the begin contains a loop. The loop counter is index, and the count-expression is the number-of-notes we need to create.
When the list ends, we return the-list of notes. In the body of the loop, we use set with @= to cons the sum of starting-note and the index onto the-list. The list cons’ing process continues until the variable index is equal to the number-of-notes. The list is returned.
To help understand the iterative process, a display statement has been inserted into the loop body.
Example 12.1.2: make-a-chromatic-lick.sal
define function make-a-chromatic-lick(
starting-note, number-of-notes) begin
with the-list loop
for index below number-of-notes
set the-list @= starting-note + index display "make-a-lick", index, the-list end
return the-list end
When we call the function, we get the following results:
Example 12.1.3: output from make-a-chromatic-lick
SAL> print make-a-chromatic-lick(60, 6) make-a-lick : INDEX = 0 THE-LIST = (60) make-a-lick : INDEX = 1 THE-LIST = (61 60) make-a-lick : INDEX = 2 THE-LIST = (62 61 60) make-a-lick : INDEX = 3 THE-LIST = (63 62 61 60) make-a-lick : INDEX = 4 THE-LIST = (64 63 62 61 60) make-a-lick : INDEX = 5 the-list = (65 64 63 62 61 60)
{65 64 63 62 61 60}
Why does the list go from largest to smallest? Because we cons’ed the newly created element onto the front of the list (using
@=). If we want a list in ascending order, we could use the reverse function on the-list. Alternatively, we could use the &= operator to put the newly created elements at the end of the list. Note that extending lists at the end takes longer than cons’ing to the front because the computer must first find the end of the list. Because it is more efficient, cons’ing followed by a list reversal is a common coding pattern. (Unless lists are very long, you are unlikely to notice any difference in evaluation time.)
Example 12.1.4: make-a-chromatic-lick-2.sal, a revision
SAL> define function make-a-chromatic-lick(
starting-note, number-of-notes) begin
loop
with the-list
for index below number-of-notes set the-list @= starting-note + index display "make-a-lick", index, the-list finally return reverse(the-list) end
end
SAL> print make-a-chromatic-lick(60, 6) make-a-lick : index = 0 the-list = (60) make-a-lick : index = 1 the-list = (61 60) make-a-lick : index = 2 the-list = (62 61 60) make-a-lick : index = 3 the-list = (63 62 61 60) make-a-lick : index = 4 the-list = (64 63 62 61 60) make-a-lick : index = 5 the-list = (65 64 63 62 61 60)
{60 61 62 63 64 65}
In Example 12.1.2, we created the-list in a begin-end block so that it would still be in scope after the loop terminated, allowing us