## Control Structures

As well as the conventional branch arrow, APLX supports structured-control keywords for flow control, often making for more readable functions.

The structured control keywords are not part of the International Standards Organisation (ISO) specification of the APL language, but they are supported by a number of APL implementations including APLX.

The structured control keywords include:

Function | Keywords
Conditional execution | :If :OrIf :AndIf :ElseIf :Else :EndIf
For loop | :For :In :Leave :Continue :EndFor
While loop | :While :Until :Leave :Continue :EndWhile
Repeat loop | :Repeat :Until :Leave :Continue :EndRepeat
Case selection | :Select :Case :CaseList :Else :EndSelect
Error trapping | :Try :CatchIf :CatchAll :EndTry
Terminate current function | :Return
Branch | :GoTo

Note: The general keyword `:End` can be use in place of any of `:EndIf :EndFor :EndWhile :EndRepeat :EndSelect :EndTry`

### Using Control Structures

The keywords all begin with a colon character, and usually appear at the start of the line (APLX will automatically indent lines within a block for you). For example:

         ’ITERATE N
    [1]   :If N<0
    [2]     'Negative argument not supported'
    [3]     :Return
    [4]   :EndIf
    [5]   ...

You can also place a block on a single diamond-delimited line:

         ’ITERATE N
    [1]   :If N<0 ª 'Negative argument not supported' ª :Return ª :EndIf
    [2]   ...

Multi-line sequences can be nested to any depth, but single-line sequences cannot contain further nested control structures. Note: The single-line form cannot be used with `:Try..:EndTry`.

The APLX function editor prompts you with the correct indentation as you type. If you cut or paste lines, you can clean up the indentation from the Edit menu (or press Ctrl-I in Windows, Cmd-I under MacOS)

The supported set of structured-control phrases is as follows (items in square brackets are optional). You can end any sequence with `:End` rather than the more specific ending keyword shown. Note that in APLX, structured-control keywords are not case-sensitive when you enter them, but APLX will re-display them in the case shown.

### Conditional execution

Syntax:

`:If <boolean expression>
...
[:ElseIf <boolean expression>]
...
[:Else]
...
:EndIf`

The expression following the `:If` keyword is evaluated. If it is true, the block which follows it is executed, until an `:ElseIf`, `:Else`, `:End` or `:EndIf` is encountered, at which point execution transfers to the statement after the `:End` or `:EndIf`. If the expression is false, the same procedure is followed for any `:ElseIf` blocks in the sequence. If none of the tests is true, the `:Else` block (if any) is executed. It is permissible to have as many `:ElseIf` sections as you like.

For example, this function returns a string which depends on the value of B:

          ’R„CLASSIFY B
    [1]   :If B=0
    [2]     R„'Zero'
    [3]   :ElseIf B>0
    [4]     R„'Positive'
    [5]   :Else
    [6]     R„'Negative'
    [7]   :End
          ’

You can also add `:AndIf` or `:OrIf` phrases after an `:If` or `:ElseIf` phrase. If you use `:AndIf`, each expression must be true for the block to be executed, whereas if you use `:OrIf` only one of them needs to be true. (The `:AndIf` and `:OrIf` conditional expressions are evaluated only if necessary). For example:

          ’R„A CLASSIFY B
    [1]   :If B=0
    [2]   :AndIf A=0
    [3]     R„'Both arguments are zero'
    [4]   :ElseIf B=0
    [5]   :OrIf A=0
    [6]     R„'One argument is zero'
    [7]   :Else
    [8]     R„'Neither argument is zero'
    [9]   :End
          ’

### For loop

Syntax:

`:For <control variable name> :In <vector expression>
...
:EndFor`

The control variable is assigned successive values from the vector expression and the loop is executed once for each value. The values can be of any type, not just integers. The vector expression is evaluated only once, at the start of the loop. For example:

          :For W :In "It's" "Off" "To" "Work" ª 'HiHo' W ª :EndFor
     HiHo It's
     HiHo Off
     HiHo To
     HiHo Work

You can use the `:Continue` keyword within the loop to force premature termination of a particular iteration - execution continues at the top of the loop with the next value (if there is one). You can also use the `:Leave` keyword to exit the loop completely and continue execution with the line after the `:EndFor`.

### While loop

Syntax:

`:While <boolean expression>
...
:EndWhile`

If the boolean expression is true (value 1), the loop body is executed. At the end, control returns to the `:While` statement and the loop is re-executed as long as the boolean expression remains true.

          ’Evaluate B
    [1]   :While B>0
    [2]     B„NextNode B
    [3]   :EndWhile
          ’

An alternative form allows a test at the end of the loop as well:

Syntax:

`:While <boolean expression>
...
:Until <boolean expression>`

The `:Continue` and `:Leave` keywords can again be used to force an early termination of a particular iteration or of the whole loop.

### Repeat loop

Syntax:

`:Repeat [<integer expression>]
...
:EndRepeat`

The loop body is repeated a maximum of N times, where N is the value of the integer expression (evaluated only once, at the start of the loop). If the integer expression is omitted, the loop is repeated for ever, unless terminated in another way. For example:

          :Repeat 3 ª ŒTS ª :EndRepeat
    2002 7 30 14 36 2 228
    2002 7 30 14 36 2 228
    2002 7 30 14 36 2 228

The `:Continue` and `:Leave` keywords can again be used to force an early termination of a particular iteration or of the whole loop:

          ’GUESS;VAL
    [1]   'Guess a number'
    [2]   :Repeat
    [3]     VAL„Œ
    [4]     :If VAL=231153
    [5]       'You were right!'
    [6]       :Leave
    [7]     :EndIf
    [8]     'Sorry, try again..'
    [9]   :EndRepeat
          ’

You can also end the loop with an `:Until` statement so that execution repeats only if a boolean expression remains true:

`:Repeat [<integer expression>]
...
:Until <boolean expression>`

### Case selection

Syntax:

`:Select <expression>
:Case <expression>
...
[:CaseList <vector expression>]
...
[:Else]
...
:EndSelect`

The `:Select` expression can be any APL scalar or array. It is matched against each of the `:Case` expressions (or elements of the `:CaseList` expressions) in turn. If they match in value and shape (using the same rules as the APL ¦ (match) primitive), the body of lines following is executed, until the next control keyword in the sequence is reached when execution jumps to the line following the `:EndSelect` (For `:CaseList` the match is done against each of the elements of the vector expression in turn, and if any of them match then the test is regarded as true). If none of the expressions match, the `:Else` clause (if any) is executed. For example:

          ’R„CLASSIFY B;ŒIO
    [1]   ŒIO„1
    [2]   :Select B
    [3]   :Case 0
    [4]     R„'Scalar zero'
    [5]   :Case 1½0
    [6]     R„'Length 1 vector, value 0'
    [7]   :CaseList ¼10
    [8]     R„'Scalar in the range 1 to 10'
    [9]   :Else
    [10]    R„'None of the above'
    [11]  :EndSelect
          ’

        CLASSIFY 0
    Scalar zero
        CLASSIFY 2
    Scalar in the range 1 to 10
        CLASSIFY 1½2
    None of the above
        CLASSIFY 1½0
    Length 1 vector, value 0

### Error Trapping

Syntax:

`:Try
...
[:CatchIf <boolean expression>]
...
[:CatchAll]
...
:EndTry`

The block of code following the `:Try` keyword is executed, until either an error occurs, or a `:CatchIf`, `:CatchAll`, `:End` or `:EndTry` is encountered. (Unlike the other control structures, `:Try...:EndTry` blocks cannot be placed on a single line).

If no error has occurred within the `:Try` block, execution transfers to the line after the `:End` or `:EndTry`.

If an error occurs in the `:Try` block (either in the statements in this function, or in any functions called from it), control transfers to the first `:CatchIf` line, and the expression is evaluated. If it is true, the block of code following the `:CatchIf` is executed, and execution then resumes after the `:EndTry` or `:End`. If the expression is false, the same procedure is followed for any further `:CatchIf` blocks in the sequence. If none of the tests is true, the `:CatchAll` block (if any) is executed. It is permissible to have as many `:CatchIf` sections as you like.

Typically, you use the `:CatchIf` statement to catch specific types of error, by looking at ŒLER or ŒET. See the section Error trapping using :Try..:EndTry for more information.

### Miscellaneous keywords

The `:GoTo` keyword (followed by a line label name) can be used to branch directly to a label. It is equivalent to using a conventional APL … symbol to branch to a label. You can branch to a label inside the same control structure, or to a label outside the control structure, but not to a label which is more deeply nested than the line you are branching from.

The `:Return` keyword causes the current function execution to terminate. It is equivalent to a conventional APL branch to line 0.

### Named loops

Normally the `:Continue` and `:Leave` keywords apply to the current loop in which they are executed, so that if you have a loop nested within a loop, execution resumes at the start or end of the innermost loop. However, you can also name loops by including a label at the start line, and follow the `:Continue` or `:Leave` with the name to apply it to a particular level of nesting. In this example, if the `:If` clause is true, execution continues at line 9:

        ’ITERATE;N
    [1]  OUTER: :Repeat
    [2]    :For N :In SAMPLES
    [3]      :If INTERRUPTED
    [4]        :Leave OUTER
    [5]      :EndIf
    [6]      ...
    [7]    :EndFor
    [8]  :EndRepeat
    [9]  ...

### Errors

If there is an error in the usage of structured keywords, APLX will report a STRUCTURED CONTROL ERROR. This typically arises if the keywords at the beginning and end of the block do not match up correctly, or if you branch to a line label within a control structure without executing the initial keyword line at the start of the block.

Note that APLX does not prevent you from fixing a function which is syntactically incorrect. However, the APLX editor will warn you of mismatched structured-control keywords if you select 'Clean up indentation' from the Edit menu (Ctrl-I in Windows, Cmd-I under MacOS).

Topic: APLX Help : Help on APL language : APL Fundamentals : Control structures

[ Previous | Next | Contents | Index ]