Topic: APLX Help : Help on APL language : APL Fundamentals : Control structures
[ Previous | Next | Contents | Index | APL Home ]

www.microapl.co.uk

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:

FunctionKeywords
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 | APL Home ]