Structures in AMPLE – part 3

Kevin Doyle

There are three main types of structure available in AMPLE:

a) Loops;

b) Conditionals;

c) Conditional loops.

I am examining each of these in turn over the first few issues of AMPLINEX and giving examples of their use. In this issue I will look at conditional loops.

Conditional loops in AMPLE

In the first of these three articles I looked at simple loops using the FOR(...)FOR structure. This allowed any AMPLE expression to be performed a specified number of times. In many cases, however, the AMPLE programmer may not want to specify the number of times the loop is to be performed. For instance, in the early stages of composition it may be desirable to play a repeating rhythm or bass line whilst trying different melodic lines on another voice. In such cases the number of loops is not known in advance.

What is needed is an unlimited 'infinite' loop, to play the rhythm or bassline as long as required.

To do this the REP(...)REP structure can be used. The AMPLE expression between the two brackets is then repeated until the program is stopped. So, to repeat a simple bass line the following word might be created:

"part1" [ % repeating bass line

REP( 48, -1: GGeeccDD )REP]

which will continue until the ESCAPE key is pressed.

The REP(...)REP structure can also be given a conditional section to allow exit from the loop.

This conditional loop uses a REP(...)UNTIL(...)REP structure. The contents of the AMPLE expressions between the brackets is rather more complex than with the conditionals discussed in the second article. This is because the expression to be performed and the expression to be evaluated as ON (true) or OFF (false) are both held within the structure and the expression to be performed can be within either or both sets of brackets.

The form of the conditional loop can be described in more detail as:

REP( action1 test )UNTIL( action2 )REP

where the presence of action1 and action2 is optional.

As with all the structures in AMPLE the action expressions could be empty in which case the loop would merely serve a 'pausing' function.

For example, to provide a pause for a keypress the following word could be defined:

"spacewait" [ % wait for space bar

"Press the space bar to continue" $OUT

REP( #IN 32 #= )UNTIL( )REP ]

which will print the message and wait for a keypress, test if it equals 32 (i.e. a space) and then end if it does or wait for another keypress if it doesn't.

Any expression placed before the test in the first set of brackets will be performed at least once. So, to return to the earlier example of a repeating bass line the structure could be changed so that the loop repeats until the CTRL key is pressed:

"part1" [ % repeat bass line until

% CTRL key is pressed

REP( 48, -1: GGeeccDD

-2 QKEY )UNTIL( )REP ]

where -2 is the code for the CTRL key (see BBC User Guide entry for BASIC word INKEY) and QKEY returns a ON if this key is being pressed or OFF if not.

Because the key is only checked after each performance of the bass line the CTRL key may have to pressed for a few seconds to cause the loop to end.

As mentioned earlier, there is the opportunity with conditional loops to have an AMPLE expression in the second part of the structure, between the UNTIL(...)REP brackets. Any expression contained in this part of the structure is performed whenever the result of the test preceding the )UNTIL( is false. This can be useful when, for example, a simple error routine needs to be incorporated into an input loop.

So, a word could be defined to accept a number from the keyboard in the range 1-8 giving a beep if is outside this range:

"getnum" [ % get a number from 1 to 8

"Enter a number (1-8): " $OUT

REP( #IN #11 48 #> #12 57 #< AND

)UNTIL( 7#OUT )REP ]

After printing the message, the loop waits for a keypress, tests that it is greater than 0 (ASCII 48) and less than 9 (ASCII 57). If it is within these limits the loop ends. If not then the second part of the structure is performed, sounding a beep, and the loop starts again.

Structures in AMPLE - final points

In these articles I have discussed three types of AMPLE structure:

1) Loops

FOR(...)FOR

2) Conditionals

IF(...)ELSE(...)IF;

3) Conditional loops

REP(...)UNTIL(...)REP.

Each of these can only be used within words and not as commands entered at the '%' prompt.

When constructing complex, nested, structures the error '! Bad structure' may occur. If this happens check carefully through the definition to ensure that each structure is properly completed. Check that each start word such as FOR(, IF(, and REP( has a matching finishing word of )FOR, )IF and )REP and that no structures overlap thus:

REP(... FOR( ... )REP ...)FOR

Other errors associated with AMPLE structures are:

! Too many levels - this can occur if a large number of nested FOR loops is used.

! Too many numbers - this can occur if a loop is leaving an extra number each time round.

! Too many strings - this can occur if a loop is leaving an extra string each time round.

This is the last of the three articles on structures in AMPLE. If you have found these articles of use you may wish to suggest other areas of AMPLE programming which you would like to see discussed in AMPLINEX. Please send any suggestions via Feedback for the next issue.