SELECT..OF block
The SELECT..OF block is a bit more complicated than the normal SELECT block, but can be very useful.
It has the following form:
SELECT maxrange OF expression
CASE constA
statementsA
CASE constB1 TO constB2
statementsB
CASE range1, range2
statementsC
DEFAULT
statementsD
ENDSELECT
The value to be matched is expression, which can be any expression, not just a variable like in the normal SELECT block.
However, the maxrange, constA, constB1 and constB2 must all be explicit numbers, i.e., constants (see 8 Constants).
maxrange must be a positive constant and the other constants must all be between zero and maxrange (including zero but excluding maxrange).
The CASE values to be matched are specified using ranges.
A simple range is a single constant (the first CASE above).
The more general range is shown in the second CASE, using the TO keyword (constB2 must be greater than constB1).
A general CASE in the SELECT..OF block can specify a number of possible ranges to match against by separating each range with a comma, as in the third CASE above.
For example, the following CASE lines are equivalent and can be used to match any number from one to five (inclusive):
CASE 1 TO 5 CASE 1, 2, 3, 4, 5 CASE 1 TO 3, 3 TO 5 CASE 1, 2 TO 3, 4, 5 CASE 1, 5, 2, 4, 3 CASE 2 TO 3, 5, 1, 4
If the value of the expression is less than zero, greater than or equal to maxrange, or it does not match any of the constants in the CASE ranges, then the statements in the DEFAULT part are executed.
Otherwise the statements in the first matching CASE part are executed.
As in the normal SELECT block, there does not need to be a DEFAULT part.
The following SELECT..OF block prints the (numeric) day of the month nicely:
SELECT 32 OF day
CASE 1, 21, 31
WriteF('The \dst day of the month\n', day)
CASE 2, 22
WriteF('The \dnd day of the month\n', day)
CASE 3, 23
WriteF('The \drd day of the month\n', day)
CASE 4 TO 20, 24 TO 30
WriteF('The \dth day of the month\n', day)
DEFAULT
WriteF('Error: invalid day=\d\n', day)
ENDSELECT
The maxrange for this block is 32, since 31 is the maximum of the values used in the CASE parts.
If the value of day was 100, for instance, then the statements in the DEFAULT part would be executed, signalling an invalid day.
This example can be rewritten as an IF block:
IF (day=1) OR (day=21) OR (day=31)
WriteF('The \dst day of the month\n', day)
ELSEIF (day=2) OR (day=22)
WriteF('The \dnd day of the month\n', day)
ELSEIF (day=3) OR (day=23)
WriteF('The \drd day of the month\n', day)
ELSEIF ((4<=day) AND (day<=20)) OR ((24<=day) AND (day<=30))
WriteF('The \dth day of the month\n', day)
ELSE
WriteF('Error: invalid day=\d\n', day)
ENDIF
The comma separating two ranges in the CASE part has been replaced by an OR of two comparison expressions, and the TO range has been replaced by an AND of two comparisons.
(It is worth noticing the careful bracketing of the resulting expressions.)
Clearly, the SELECT..OF block is much more readable than the equivalent IF block.
It is also a lot faster, mainly because none of the comparisons present in IF block have to be done in the SELECT..OF version.
Instead the value to be matched is used to immediately locate the correct CASE part.
However, it's not all good news: the maxrange value directly affects the size of compiled executable, so it is recommended that SELECT..OF blocks be used only with small maxrange values.
See the Reference Manual for more details.
Go to the Next or Previous section, the Detailed Contents, or the Amiga E Encyclopedia.