Tutorial: Transparency and Coercion


 

A very important, implicit, and pervasive aspect of the gbeta language is that there is a very consistent transparency of entity category. When used in a given context, whatever category of entity is available will be transformed to the category requested by the context. Entity categories are object, pattern, object identity and pattern identity, including concurrent variants.

An imperative is an object context

An imperative is an object context, and that means that whatever is denoted by a name which occurs as an imperative in a program will be transformed into an object, implicitly and without special syntax which reveals what it was before the transformation. That information is available by looking up the declaration anyway.

This is good since it makes the syntax at the point of application independent of the precise category of entity declared, and this means that the declaration may be changed without affecting all the usages of that declared name.

The most basic example of this is that a name which denotes an object and a name which denotes an object reference (think "a pointer" if you like) are used in the same way,

(# 
   i: @integer;
   ir: ^integer
do 
   ...
   1->i;
   2->ir;
   ...
#)

If we decide to change i into an object reference, that is a change which is local to the declaration; the rest of the program works as before without changes.

Of course, this means that it is very un-BETA-like to give names like i and ir which reveal the choice of representation, but when presenting a transparency mechanism it is necessary to focus on exactly that which is going to become invisible.

Since this transparency is a very basic property of the BETA family of languages, the traditional BETA terminology is that "@" declares a static reference and "^" declares a dynamic reference. Think of all substance-names as "pointers"/"references" and then note that some of them are constant (static) and others are variable (dynamic). This might seem the most natural perspective, if you are used to the "everything-is-a-pointer" semantics of some other object-oriented languages. When giving the formal semantics of the language, however, the notion of a "constant pointer" is an unnecessary complication compared to saying that a name simply "is" an object.

Method invocation is coercion!

A very important example of the imperative as an object context is method invocation. If a name which denotes a pattern occurs as an imperative, the pattern is coerced into an object (this transformation from pattern to object is normally called "object instantiation"), and the resulting, anonymous object is executed. As an example:

(# i: @integer;
   p: (# do i+1->i #);
   x: @(# j: @integer do j+i->i #)
do
   p;
   x;
#)

In this example, it is not possible to detect syntactically at the application of the names p and x that p is a pattern (which is implicitly instantiated to create a "procedure activation record"), whereas x is an object which is simply executed (hence keeping its local state intact between "invocations").

As a consequence of this, a pattern may be thought of as a procedure or method, since applying them as an imperative "works like" an invocation as known in other imperative languages.

An evaluation is also an object context

Since an evaluation is also an object context, the mechanism of the following examples are the same as explained above:

(# i: @integer;
   ir: ^integer;
   p: (# enter ir do (if ir<i then i-ir else i+ir if)->i 
      exit 2*i 
      #);
   x: @(# j: @integer enter j do j+i->i #)
do
   ...
   i+ir->putint;
   ((x,x),x)->(max,p)->min->putint;
   ...
#)

When i is printed with the assignment evaluation i+ir->putint, the transformation of i is a no-op since it is already an object. However, ir is coerced from object reference to object. You may think of it as "dereferencing a pointer." On the right hand side of the assignment evaluation, putint is coerced from a pattern into an object, i.e. an instance is created, and this instance is then executed.

The next imperative is a composite (multiple) assignment evaluation. Everywhere, whether a name delivers a value (it occurs before ->), or a value is impressed upon it (it occurs after ->), or both (it occurs between two ->'s), patterns are instantiated and object references are dereferenced implicitly. The if-imperative in p is covered later.

The next section deals with a number of non-object contexts.

 


Signed by: eernst@cs.auc.dk. Last Modified: 3-Jul-01