Loop Example: Nested Loops

Home, Up: Loop and Script Examples

 

In this example: Nested Loops, Using a DO Loop, Using GOTO Loops, Increasing a Variable by 1.

 

Nested Loops

Some tasks require nested loops. If you know any programming languages, you're probably familiar with something like this (the actual syntax varies between languages):

 

FOR I1 = 1 TO N1

  FOR I2 = 1 TO N2

    . . .

  NEXT

NEXT

 

You cannot do this in Hypatia, but you can still have nested loops by using your own loop variables.

Hypatia lets you do this in two different ways:

- with a script that runs in a DO loop,

- with a script that uses GOTO loops.

 

To demonstrate how this works, let's use a trivial example: creating a multiplication table.

This is done row by row -- the outer loop variable constitutes the rows, and the inner loop variable the columns.

At the start the script will ask how many rows and how many columns our table shall have.

Buffer mode gets started, and both the row and column variables are initialized.

Now the nested loops begin:

At the beginning of each row a line break is written to the buffer with the command && (when the buffer is empty, this command is ignored).

The calculation that uses the two variables is performed (the line $row $col * &), the result gets written to the buffer in accumulation mode -- of course, what you do with nested loops will probably be more complex and have more lines than the simple multiplication we use in our example.

The column variable is increased by 1.

If this makes the column variable exceed its maximum, it is set back to 1, and the row variable is increased by 1.

If the column variable exceeds its maximum, the loop is ended, and a message is displayed.

 

Blank lines and indents (spaces or tabs) are ignored by Hypatia, we use them here only to make the script better readable.

 

1) Using a DO Loop

Let's first do our task with a DO loop. The script, let's call the script file mtable1, could look like this:

 

I1: PROMPT $nrows Enter number of rows for multiplication table:

I1: PROMPT $ncols Enter number of columns:

I1: BUFFER START

I1: $row = 1

I1: $col = 1

IF $col 1 == THEN &&

 

$row $col * &

 

$col = $col 1 +

IF $col $ncols >> THEN $col = 1

ALSO: $row = $row 1 +

IF $row $nrows >> THEN ENDLOOP

I*: # The multiplication table is stored in the result buffer

I*: # Save it to a file with the command BUFFER SAVE filename

 

(Alternatively the script itself could save the buffer to a file, but then the file name would have to be specified in the script.)

You have to call this script in an infinite loop:

_*mtable1

(which is short for DO * :: _mtable1 which is short for DO * :: RUN mtable1) and afterwards save the buffer to a file.

If you open that file in an editor the columns will not be properly aligned. You can replace spaces with commas and then open the file in a program that understands CSV (comma-separated values), but for demonstrating nested loops in Hypatia, we've done well enough.

 

2) Using GOTO Loops

Using the same outer and inner loop variables -- our rows and columns -- we can do this with GOTO loops instead of a DO loop.

In this example (though it could be done differently) the initial values of row and column variables are 0, and they get increased by 1 before the calculation line (the line $row $col * &).

Let's call this script file mtable2:

 

PROMPT $nrows Enter number of rows for multiplication table:

PROMPT $ncols Enter number of columns:

BUFFER START

$row = 0

$col = 0

 

LABEL: nextrow

$row = $row 1 +

&&

 

  LABEL: nextcol

  $col = $col 1 +

 

  $row $col * &

 

  IF $col $ncols << THEN GOTO nextcol

 

$col = 0

IF $row $nrows << THEN GOTO nextrow

 

#: The multiplication table is stored in the result buffer

#: Save it to a file with the command BUFFER SAVE filename

ABORT

 

This script, unlike the previous one, must not be called in a loop -- that is, you have to run it with _mtable2, not _*mtable2.

The last line ABORT is there in case the script is accidentally run in a loop -- if this happens, the script is aborted at the end of the first pass.

Alternatively, you could put the following line at the beginning of the script:

IF ISLOOP THEN ABORT This script must not be run in a loop!

 

Whether you use DO or GOTO loops is entirely up to you -- many tasks can be done equally well in both ways, for others either the one or the other may recommend itself, but use whatever feels more natural to you.

And of course both the above examples could be written differently, but to discuss various possible variations would go beyond the scope of this documentation.

 

Increasing a Variable by 1

It may not really be worth the effort, but you can shorten a line that increases the value of a variable by 1 (like $row = $row 1 +) with a user-defined element and the pseudo constant DUP.

Instead of

$myvariable = $myvariable 1 +

you can write

$myvariable = DUP 1 +

(see paragraph "The $myvar = Assign Command" on page Using Variables in chapter "Variables and User-Defined Constants".)

 

But you can shorten this further by using a UDE, let's call it @plus1:

@plus1 = = DUP 1 +

(The first equal sign is the UDE assignment command, the second one is the beginning of the UDE's content. Spaces are required!)

If you add the above line to the configuration file hy.ini (you remember: EDINI), you can then use it in your scripts -- the line

$myvariable @plus1

will then increase the value of that variable by one.

 

Home, Up: Loop and Script Examples, Prev: Loop Example: Iteration (Babylonian Root), Next: Loop Example: Monte Carlo Experiment