Subsections

Conformity clauses

In the last section, we discussed the consequences of the uniting coercion; that is, how values of various modes can be united to values of united modes. This raises the question of how a value of a united mode can be extracted since its constituent mode cannot be determined at compile-time. There is no de-uniting coercion in Algol 68. The constituent mode or the value, or both, can be determined using a variant of the case clause discussed in chapter 4 (see section 4.6). It is called a conformity clause. For our discussion, we shall use the declaration of u in section 8.1 (u has mode STRINT).

The constituent mode of u can be determined by the following:

   CASE u IN
      (INT):    print("u is an integer")
      ,
      (STRING): print("u is a string")
   ESAC

If the constituent mode of u is INT, the first case will be selected. Notice that the mode selector is enclosed in parentheses and followed by a colon. Otherwise, the conformity clause is just like the case clause (in fact, it is sometimes called a conformity case clause). This particular example could also have been written

   CASE u
   IN
      (STRING): print("u is a string")
   OUT
      print("u is an integer")
   ESAC

This is the only circumstance when a CASE clause can have one choice. Usually, however, we want to extract the value. A slight modification is required:

   CASE u IN
      (INT i):
         print(("u identifies the value",i))
      ,
      (STRING s):
         print(("u identifies the value ",s))
   ESAC

In this example, the mode selector and identifier act as the left-hand side of an identity declaration. The identifier can be used in the following unit (or enclosed clause).

The two kinds of conformity clause can be mixed. For example, here is one way of using the procedure ucis:

   CASE ucis(c,s) IN
      (VOID):
         print("The character was not found"),
      (INT p):
         print(("The position was",p))
   ESAC

We mentioned in the last section that operators with united-mode operands can be declared. Here is one such:

   MODE IC = UNION(INT,CHAR);
   OP * = (IC a,b)IC:
   CASE a IN
      (INT ai):
         (b|(INT bi): ai*bi,
            (CHAR bc): ai*bc),
      (CHAR ac):
         (b|(INT bi): ac*bi,
            (CHAR bc): ABS ac*ABS bc)
   ESAC

In each of the four cases, the resulting product is united to the mode IC.

You can have more than one mode in a particular case. For example:

   MODE ICS = UNION(INT,CHAR,STRING);
   OP * = (ICS a,INT b)ICS:
   CASE a
   IN
      (UNION(STRING,CHAR) ic):
         (ic|(CHAR c): c*b,(STRING s): s*b),
      (INT n): n*b
   ESAC

Note that conformity clauses do not usually have an OUT clause because the only way of extracting a value is by using the (MODE id): construction. However, they do have their uses. See the standard prelude for more examples of conformity clauses.

Although read and print use united modes in their call, you cannot read a value of a united mode or print a value of a united mode (remember that united modes do not introduce new values). You have to read a value of a constituent mode and then unite it, or extract the value of a constituent mode and print it.


Exercises

8.7
The modes
   MODE IRC = UNION(INT,REAL,COMPL),
        MIRC= UNION([]INT,[]REAL,[]COMPL)
are used in this and the following exercises. Write a procedure which takes a single parameter of mode MIRC and which yields the sum of all the elements of its parameter as a value with mode IRC. Ans[*]
8.8
Write the body of the operator * whose header is declared as
   OP * = (IRC a,b)IRC:
Use nested conformity clauses. Remember that there are 9 separate cases. Ans[*]


Sian Mountbatten 2012-01-19