Control Structures: Difference between revisions

From NARS2000
Jump to navigationJump to search
 
(8 intermediate revisions by 3 users not shown)
Line 45: Line 45:
       <td></td>
       <td></td>
       <td></td>
       <td></td>
       <td>Repeatedly execute the statements between <apll>:repeat</apll> and <apll>:until</apll> until <i>expr</i> is <apll>0</apll>.</td>
       <td>Repeatedly execute the statements between <apll>:repeat</apll> and <apll>:until</apll> until <i>expr</i> is <apll>1</apll>.</td>
     </tr>
     </tr>


Line 139: Line 139:
<apll>:goto <i>expr</i></apll>
<apll>:goto <i>expr</i></apll>


This statement transfers control to the line number specified in <i>expr</i>.  The value of <i>expr</i> must be a numeric simple scalar or one-element vector.  This statement is equivalent to <apll>→<i>expr</i></apll>.
This statement transfers control to the line number specified in <i>expr</i>.  The value of <i>expr</i> must be a numeric simple scalar or one-element vector.  This statement is equivalent to <tt>[[]]<i>expr</i></tt>.


== IF Statement ==
== IF Statement ==
Line 200: Line 200:
This statement exits the current function and is equivalent to <apll>→0</apll>.
This statement exits the current function and is equivalent to <apll>→0</apll>.


== SELECT Statement ==
== SELECT/SWITCH Statements ==


<table summary="">
<tr>
  <td>
<apll>:select <i>expr1</i></apll><br />
<apll>:select <i>expr1</i></apll><br />
<apll>:case <i>expr2</i></apll><br />
<apll>:case <i>expr2</i></apll><br />
Line 210: Line 213:
... (Block of statements)<br />
... (Block of statements)<br />
<apll>:endselect</apll>
<apll>:endselect</apll>
  </td>
  <td>&nbsp;&nbsp;&nbsp;<b>OR</b>&nbsp;&nbsp;&nbsp;</td>
  <td>
<apll>:switch <i>expr1</i></apll><br />
<apll>:case <i>expr2</i></apll><br />
... (Block of statements)<br />
<apll>:caselist <i>expr3</i></apll><br />
... (Block of statements)<br />
<apll>:else</apll><br />
... (Block of statements)<br />
<apll>:endswitch</apll>
  </td>
</tr>
</table>


This statement provides a mechanism for making a choice from multiple cases as to which block of statements is executed.  The <apll>:select</apll> statement expression is evaluated and compared against each successive <apll>:case</apll> expression and the successive items in each <apll>:caselist</apll> expression.  Control is given to the first block of statements whose corresponding expression (or expression item in the case of <apll>:caselist</apll>) matches the <apll>:select</apll> expression.
This statement provides a mechanism for making a choice from multiple cases as to which block of statements is executed.  The <apll>:select</apll> statement expression is evaluated and compared against each successive <apll>:case</apll> expression and the successive items in each <apll>:caselist</apll> expression.  Control is given to the first block of statements whose corresponding expression (or expression item in the case of <apll>:caselist</apll>) matches the <apll>:select</apll> expression.
Line 226: Line 243:


Because of the way <apll>:select</apll> statements are executed, a line with a <apll>:case</apll> or <apll>:caselist</apll> statement may not be a branch target; otherwise a <apll>DESTINATION ERROR</apll> is signaled.  That is, a <apll>:select</apll> statement may be entered at the top only.
Because of the way <apll>:select</apll> statements are executed, a line with a <apll>:case</apll> or <apll>:caselist</apll> statement may not be a branch target; otherwise a <apll>DESTINATION ERROR</apll> is signaled.  That is, a <apll>:select</apll> statement may be entered at the top only.
<apll>:switch</apll> is an alias for <apll>:select</apll>; in the above discussion wherever <apll>:select</apll> appears, you may substitute <apll>:switch</apll>.
<br><br><font color=green><strong>
== Cases Branching Example 1 ==
As an alternative to the Select/Switch control structure(s) above, for a pure original APL solution to Multiple Cases scenarios in a user-function, consider using the following APL control structure. For example the following <u>user-function</u>, has one local variable (boolCases) with 6 different cases handled:<br>
<u>BranchingExample1</u>;boolCases<br>
[1]  ⍝MULTIPLE CASES: Branching/GoTo Example #1<br>
[2]  boolCases←0 1 1 1 0 0 &nbsp; &nbsp; &nbsp; ⍝Leftmost boolean 1 determines which case or block will be executed { 0 <u>1</u> 1 1 0 0 }<br>
[3]  →boolCases/(Label1 <u>Label2</u> Label3 Label4 Label5 Label6)<br>
[4]  'Did NOT branch, Case ELSE.'<br>
[5]  →Next1<br>
[6]  Label1: 'Do this, Label1'<br>
[7]  →Next1<br>
[8]  <u>Label2</u>: 'Do this, Label2' &nbsp; &nbsp; &nbsp; &nbsp; ⍝This case <u>will</u> get branched to based on boolCases!<br>
[9]  →Next1<br>
[10]  Label3: 'Do this, Label3'<br>
[11]  →Next1<br>
[12]  Label4: 'Do this, Label4'<br>
[13]  →Next1<br>
[14]  Label5: 'Do this, Label5'<br>
[15]  →Next1<br>
[16]  Label6: 'Do this, Label6'<br>
[17]  Next1: 'Code continues here.'<br>
<br>
&nbsp; &nbsp; &nbsp; &nbsp; BranchingExample1 &nbsp; &nbsp; &nbsp; ⍝User-session, <u>BranchingExample1</u> ''typed in by user''.<br>
Do this, Label2<br>
Code continues here.<br>
</strong></font>


== WHILE Statement ==
== WHILE Statement ==
Line 256: Line 301:
The expressions must evaluate to a Boolean-valued scalar or one-element vector.
The expressions must evaluate to a Boolean-valued scalar or one-element vector.


In the righthand form above, the block of statements is executed and then the expression is executed.  It must evaluate to a Boolean-valued scalar or one-element vector.  If the expression is true, the Control Structure terminates and execution continues with the statement after the <apll>:until</apll> statement; if the expression is false, execution continues at the start of the Control Structure.
In the righthand form above, if the <apll>:while</apll> expression evaluates to a scalar or one-element vector whose value is <apll>1</apll>, the block of statements is executed and then the <apll>:until</apll> expression is executed.  It must evaluate to a Boolean-valued scalar or one-element vector.  If the <apll>:until</apll> expression is true, the Control Structure terminates and execution continues with the statement after the <apll>:until</apll> statement; if the <apll>:until</apll> expression is false, execution continues at the start of the Control Structure.


The <apll>:while</apll> statement may be followed by zero or more <apll>:andif</apll> statements to narrow the conditions under which the block of statements is executed, or it may be followed by zero or more <apll>:orif</apll> statements to widen the conditions under which the block of statements is executed.  The <apll>:andif</apll> and <apll>:orif</apll> statements may not be mixed after a <apll>:while</apll> statement.
The <apll>:while</apll> statement may be followed by zero or more <apll>:andif</apll> statements to narrow the conditions under which the block of statements is executed, or it may be followed by zero or more <apll>:orif</apll> statements to widen the conditions under which the block of statements is executed.  The <apll>:andif</apll> and <apll>:orif</apll> statements may not be mixed after a <apll>:while</apll> statement.
Line 263: Line 308:


To interrupt the flow of control within a block of statements, use the <apll>:continue</apll> or <apll>:leave</apll> keywords.  The former keyword transfers control to the end of the block continuing with the next repetition, skipping the statements between the <apll>:continue</apll> and matching <apll>:endwhile</apll> or <apll>:until</apll> keywords, but evaluating and acting upon an <apll>:until</apll> statement, if present.  The latter keyword exits the <apll>:while</apll> loop entirely and transfers control to the statement after the matching <apll>:endwhile</apll> or <apll>:until</apll> statement.  Typically, these two keywords appear within <apll>:if</apll> statements.
To interrupt the flow of control within a block of statements, use the <apll>:continue</apll> or <apll>:leave</apll> keywords.  The former keyword transfers control to the end of the block continuing with the next repetition, skipping the statements between the <apll>:continue</apll> and matching <apll>:endwhile</apll> or <apll>:until</apll> keywords, but evaluating and acting upon an <apll>:until</apll> statement, if present.  The latter keyword exits the <apll>:while</apll> loop entirely and transfers control to the statement after the matching <apll>:endwhile</apll> or <apll>:until</apll> statement.  Typically, these two keywords appear within <apll>:if</apll> statements.
[[Category:Examples]]

Latest revision as of 19:24, 15 March 2024

Overview

:for varname :in expr... ⋄ :endfor Loop through the elements of expr assigning each value to varname, and then execute the statements between :for and :endfor.
:forlcl varname :in expr... ⋄ :endforlcl Same as :for except that the varname is localized to the :forlcl / :endforlcl control structure.
:goto expr Execute expr.
:if expr... ⋄ :endif Execute the statements between :if and :endif iff expr is 1.
:repeat ⋄ ... ⋄ :endrepeat Repeatedly execute the statements between :repeat and :endrepeat.
:repeat ⋄ ... ⋄ :until expr Repeatedly execute the statements between :repeat and :until until expr is 1.
:return Execute →0.
:select expr1 ⋄ :case expr2...
⋄ :caselist expr3... ⋄ :endselect
Execute a specific block of statements depending upon which :case or :caselist expression matches expr1.
:switch expr1 ⋄ :case expr2...
⋄ :caselist expr3... ⋄ :endswitch
Same as :select.
:while expr... ⋄ :endwhile Repeatedly execute the statements between :while and :endwhile while expr is 1.
:while expr1... ⋄ :until expr2 Repeatedly execute the statements between :while and :until while expr1 is 1 and expr2 is 0.


  • All Control Structures may be placed all or partly on one line as in :for I :in ⍳12 ⋄ ... ⋄ :endfor (very convenient for use in immediate execution mode), or on multiple lines as in
    :for I :in ⍳12
    ...
    :endfor

  • As usual for any statement, a label may be used at the beginning of any line even if it starts with a Control Structure. For example,
    [3] L1::if I < 10 ⋄ ...
  • Each Control Structure that closes with a statement-specific keyword (:endfor, :endforlcl, :endif, :endrepeat, :endselect, :endswitch, and :endwhile), may instead close with the :end keyword.


FOR/FORLCL Statements

:for varname :in expr :forlcl varname :in expr
... (Block of statements) ... (Block of statements)
:endfor :endforlcl

These statements evaluate expr once, loop through its elements, assign each successive value to varname, and then execute the block of statements once for each value in expr. The expr may be of any type (including character and nested), any rank, and any shape. If expr is empty, the block of statements is skipped.

With the :for statement, the varname is not localized to the :for loop; upon exiting the loop, varname has the last value assigned to it by the :for loop.

With the :forlcl statement, the varname is localized to the :forlcl loop; upon exiting the loop, varname has the value assigned to it before the :forlcl loop started.

To interrupt the flow of control within a block of statements, use the :continue or :leave keywords. The former keyword transfers control to the end of the block continuing with the next iteration, thus skipping the statements between the :continue and matching :endfor/:endforlcl keywords. The latter keyword exits the :for/:forlcl loop entirely and transfers control to the statement after the matching :endfor/:endforlcl statement. Typically, these two keywords appear within :if/:endif statements.

GOTO Statement

:goto expr

This statement transfers control to the line number specified in expr. The value of expr must be a numeric simple scalar or one-element vector. This statement is equivalent to expr.

IF Statement

:if expr1
... (Block of statements)
:elseif expr2
... (Block of statements)
:else
... (Block of statements)
:endif

This statement conditionally executes a block of statements.

Each expression must evaluate to a Boolean-valued scalar or one-element vector.

Each :if and :elseif statement may be followed by zero or more statements which form the block of statements controlled by that statement.

The :if statement may be followed by zero or more :elseif blocks. Optionally, the :else statement may appear after all :elseif statements to handle the case where none of the previous expressions was true (evaluated to a 1).

Each :if and :elseif statement may be followed by zero or more :andif statements to narrow the conditions under which the following block of statements is executed, or may be followed by zero or more :orif statements to widen the conditions under which the following block of statements is executed. The :andif and :orif statements may not be mixed within any :if or :elseif statement.

REPEAT Statement

:repeat :repeat
... (Block of statements) ... (Block of statements)
:endrepeat :until expr

This statement executes a block of statements repeatedly (but at least once) until the :until expression is true, or control transfers out of the Control Structure.

In the righthand form above, the block of statements is executed and then the expression is executed. It must evaluate to a Boolean-valued scalar or one-element vector. If the expression is true, the Control Structure terminates and execution continues with the statement after the :until statement; if the expression is false, execution continues at the start of the Control Structure.

The :until statement may be followed by zero or more :andif statements to widen the conditions under which the block of statements is executed, or it may be followed by zero or more :orif statements to narrow the conditions under which the block of statements is executed. The :andif and :orif statements may not be mixed after an :until statement.

To interrupt the flow of control within a block of statements, use the :continue or :leave keywords. The former keyword transfers control to the end of the block continuing with the next repetition, skipping the statements between the :continue and matching :endrepeat or :until keywords. The latter keyword exits the :repeat loop entirely and transfers control to the statement after the matching :endrepeat or :until statement. Typically, these two keywords appear within :if statements.

RETURN Statement

:return

This statement exits the current function and is equivalent to →0.

SELECT/SWITCH Statements

:select expr1
:case expr2
... (Block of statements)
:caselist expr3
... (Block of statements)
:else
... (Block of statements)
:endselect

   OR   

:switch expr1
:case expr2
... (Block of statements)
:caselist expr3
... (Block of statements)
:else
... (Block of statements)
:endswitch

This statement provides a mechanism for making a choice from multiple cases as to which block of statements is executed. The :select statement expression is evaluated and compared against each successive :case expression and the successive items in each :caselist expression. Control is given to the first block of statements whose corresponding expression (or expression item in the case of :caselist) matches the :select expression.

For the :case statement, its expression is compared with the :select statement's expression. The comparison uses the Match function (≡), so it takes into account rank and shape at every level.

For the :caselist statement, the successive items in its expression are compared with the :select statement's expression. As with the :case statement the comparison uses the Match function. The :case statements allows you to combine multiple selection criteria into one expression. It is equivalent to the C language use of multiple case statements preceding a block of statements.

Unlike the C language switch statement, the :case and :caselist expressions need not be constant, and there may be multiple :case or :caselist statements whose expressions evaluate to the same value — however only the earliest occurrence is selected.

When the last statement in a block of statements is executed, the system exits the :select control structure. The :leave statement may be used to exit that block before reaching the last statement, similar to the C language break statement.

Each :case and :caselist statement may be followed by zero or more statements which form the block of statements controlled by that statement.

The :select statement may be followed by a mixture of zero or more :case and :caselist blocks. Optionally, the :else statement may appear after all :case and :caselist statements to handle the case where none of the previous :case or :caselist expressions match the :select expression — in this context, the :else statement is similar to the C language default statement.

Because of the way :select statements are executed, a line with a :case or :caselist statement may not be a branch target; otherwise a DESTINATION ERROR is signaled. That is, a :select statement may be entered at the top only.

:switch is an alias for :select; in the above discussion wherever :select appears, you may substitute :switch.

Cases Branching Example 1

As an alternative to the Select/Switch control structure(s) above, for a pure original APL solution to Multiple Cases scenarios in a user-function, consider using the following APL control structure. For example the following user-function, has one local variable (boolCases) with 6 different cases handled:
BranchingExample1;boolCases
[1] ⍝MULTIPLE CASES: Branching/GoTo Example #1
[2] boolCases←0 1 1 1 0 0       ⍝Leftmost boolean 1 determines which case or block will be executed { 0 1 1 1 0 0 }
[3] →boolCases/(Label1 Label2 Label3 Label4 Label5 Label6)
[4] 'Did NOT branch, Case ELSE.'
[5] →Next1
[6] Label1: 'Do this, Label1'
[7] →Next1
[8] Label2: 'Do this, Label2'         ⍝This case will get branched to based on boolCases!
[9] →Next1
[10] Label3: 'Do this, Label3'
[11] →Next1
[12] Label4: 'Do this, Label4'
[13] →Next1
[14] Label5: 'Do this, Label5'
[15] →Next1
[16] Label6: 'Do this, Label6'
[17] Next1: 'Code continues here.'

        BranchingExample1       ⍝User-session, BranchingExample1 typed in by user.
Do this, Label2
Code continues here.

WHILE Statement

:while expr1 :while expr1
... (Block of statements) ... (Block of statements)
:endwhile :until expr2

This statement executes a block of statements repeatedly until the :while expression is false, or the :until expression is true, or control transfers out of the Control Structure.

The expressions must evaluate to a Boolean-valued scalar or one-element vector.

In the righthand form above, if the :while expression evaluates to a scalar or one-element vector whose value is 1, the block of statements is executed and then the :until expression is executed. It must evaluate to a Boolean-valued scalar or one-element vector. If the :until expression is true, the Control Structure terminates and execution continues with the statement after the :until statement; if the :until expression is false, execution continues at the start of the Control Structure.

The :while statement may be followed by zero or more :andif statements to narrow the conditions under which the block of statements is executed, or it may be followed by zero or more :orif statements to widen the conditions under which the block of statements is executed. The :andif and :orif statements may not be mixed after a :while statement.

The :until statement may be followed by zero or more :andif statements to widen the conditions under which execution the block of statements is executed, or it may be followed by zero or more :orif statements to narrow the conditions under which the block of statements is executed. The :andif and :orif statements may not be mixed after an :until statement.

To interrupt the flow of control within a block of statements, use the :continue or :leave keywords. The former keyword transfers control to the end of the block continuing with the next repetition, skipping the statements between the :continue and matching :endwhile or :until keywords, but evaluating and acting upon an :until statement, if present. The latter keyword exits the :while loop entirely and transfers control to the statement after the matching :endwhile or :until statement. Typically, these two keywords appear within :if statements.