4 Virtual Pattern

4.1 Structural equivalence is used in BETA

In the example in section 3 it was mentioned that a redefinition of a virtual procedure pattern is not a redefinition (overriding) as in C++. In fact a virtual pattern in BETA can only be extended and cannot be completely redefined. The rationale behind this is that a subpattern should have the same properties as its superpattern including which imperatives are executed. Ideally a subpattern should be behaviorally equivalent to its superpattern. This will, however, require a correctness proof. The subpattern mechanism of BETA supports a form of structural equivalence between a subpattern and its superpattern.

Consider the following patterns:

4.2 Patterns A and AA

A: (# V:< (# x:  do I1; inner; I2 #) #);
AA: A(# V::< (# y:  do I3; inner; I4#) #)

The pattern A has a virtual procedure attribute V. V has an attribute x and its do-part contains the execution of I1; inner; I2. The subpattern AA of A extends the definition of V. The extended definition of V in AA corresponds to the following object-descriptor (except for scope rules):

4.3 Combined descriptor

(# x: ; y:  do I1; I3; inner; I4; I2 #)

As may be seen the V attribute of AA has the attributes x and y and the do-part consists of I1; I3; inner; I4; I2. The definition of V is an extension of the one from A and not a replacement.

The subpattern AB of A describes another extension of V:

4.4 Pattern AB

AB: A(# V::< (# z:  do I5; inner; I6 #) #)

Here V corresponds to the following object descriptor:

V: (# x: ; z:  do I1; I5; inner; I6; I2 #)

The definition of V may be further extended in subpatterns of AA also as shown in the definition AAA:

4.5 Pattern AAA

AAA: AA(# V::< (# q:  do I7; inner; I8 #) #)

The definition of V corresponds to the following object-descriptor:

V: (# x: ; y: ; q:  do I1; I3; I7; inner; I8; I4; I2 #)

As may be seen, the pattern V is a combination of the definitions of V from A, AA and AAA.

4.6 Final binding

The definition of V may be extended using a final binding (::) in subpatterns of A as shown in the definition AC:

AC: A(# V::(# q:  do I2; inner; I4 #) #)

The final binding of V means that V cannot be extended in subpatterns of AC. The extended definition of V in AC corresponds to the following object-descriptor (except for scope rules):

(# x: ; y:  do I1; I3; inner; I4; I2 #)

The virtual mechanism in BETA guarantees that behavior defined in a superpattern cannot be replaced in a subpattern. This form of structural equivalence is useful when defining libraries of patterns that are supposed to execute a certain sequence of actions. In C++, the programmer must explicitly invoke the actions from the superclass by means of superclass::functionname. This is illustrated by the example in the next section.

The inner construct is more general than shown above, since a pattern may have more than one inner and inner may appear inside control structures and nested singular object descriptors.

4.7 Virtual Procedure Pattern

The attribute computeSalary of pattern employee is an example of a virtual procedure pattern. In this example the do-part of the virtual definition in employee is very simple, only consisting of an inner-imperative. The extended definitions of computeSalary in worker and salesman both include the code noOfHours*80 and 0->totalHours. This code may instead be defined in the definition of computeSalary in employee as shown below:

4.7.1 ComputeSalary is a virtual procedure pattern

employee:
  (# 
     computeSalary:< 
       (# salary: @integer 
       do noOfHours*80->salary; inner; 0->totalHours 
       exit salary
       #)
  #);
  worker: employee
    (# 
       computeSalary::< (# do seniority*4+salary->salary; inner #)
    #);
  salesman: employee
    (# 
       computeSalary::<
         (# 
         do noOfSoldUnits*6+salary ->salary;
            0 ->noOfSoldUnits; 
            inner
         #)
    #)

The extended definitions of computeSalary in worker and salesman have an inner to enable further extensions of computeSalary in subpatterns of worker and salesman.

4.8 Virtual Class Pattern

Virtual patterns may also be used to parameterize general container patterns such as the register pattern described above. For the register pattern we assumed the existence of a type pattern defining the elements of the register, i.e. elements of a register must be instances of the pattern type. The pattern type may be declared as a virtual pattern attribute of register as shown below:

4.8.1 type is a virtual class pattern

register:
  (# type:< object;
     insert:< (# e: ^type enter e[] do #)
     
  #)

The declaration type:< object specifies that type is either the pattern object or some subpattern of object. In the definition of register, type may be used as an alias for object, e.g. references qualified by type are known to be at least Objects. Since object is the most general superpattern, type may potentially be any other pattern. The virtual attribute type may be bound to a subpattern of object in subpatterns of register. The following declaration shows a pattern workerRegister which is a register where the type attribute has been bound to worker:

workerRegister: register
  (# type::< worker;
     findOldestSeniority:
       (# old: @integer
       do scan
           (# do (if current.seniority > old then 
                     current.seniority->old
           if)#)
       exit old
       #)
  #);

In the definition of workerRegister, the virtual pattern type may be used as a synonym for the pattern worker. This means that all references qualified by type may be used as if they were qualified by worker. The reference current of the scan operation is used in this way by the operation findOldestSeniority which computes the oldest seniority of the register. The expression current.seniority is legal since current is qualified by type which in workerRegister is at least a worker.

In subpatterns of workerRegister it is possible to make further bindings of type thereby restricting the possible members of the register. Suppose that manager is a subpattern of worker. A manager register may then be defined as a subpattern of workerRegister:

managerRegister: workerRegister(# type::< manager #)

In the definition of managerRegister, type may be used as a synonym for manager, i.e. all references qualified by type are also qualified by manager.

4.8.2 General parameterized patterns

Virtual patterns make it possible to define general parameterized patterns like register and to restrict the member type of the elements. In this way virtual class patterns provide an alternative to templates as found in C++.


BETA Language Introduction
© 1994-2002 Mjølner Informatics
[Modified: Saturday October 21st 2000 at 18:34]