Go to the Next or Previous section, the Detailed Contents, or the Amiga E Encyclopedia.


4.1.4 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.