Support for Arrays

Sather - A Language Tutorial
Prev | Chapter 6. Parametrized Classes and Arrays | Next

# 6.2. Support for Arrays

Arrays (and, in fact, most container classes) are realized using parametrized classes in Sather. There is language support for the main array class `ARRAY{T}` in the form of a literal expressions of the form

    a:ARRAY{INT} := |1,2,3|;

In addition to the standard accessing function, arrays provide many operations, ranging from trivial routines that return the size of the array to routines that will sort arbitrary arrays. See the array class in the container library for more details. There are several aspects to supporting arrays:

- Support for accessing array elements

- Support for objects which represent arrays

- Support for initializing these arrays using literals

## 6.2.1. Array Access

The form '`a[4]:=..'` is syntactic sugar for a call of a routine named `aset`' with the array index expressions and the right hand side of the assignment as arguments. In the class TRIO below we have three elements which can be accessed using array notation

    class TRIO is
       private attr a,b,c:FLT;

       create:SAME is
          return new
       end;

       aget(i:INT):FLT is
          case i
          when 0 then return a
          when 1 then return b
          when 2 then return c
          else raise "Bad array index!\n";
          end;
       end;

       aset(i:INT, val:FLT) is
          case i
          when 0 then a := val;
          when 1 then b := val;
          when 2 then c := val;
          end;
       end;
    end;

The array notation can then be used with objects of type TRIO

    trio:TRIO := #TRIO;  -- Calls TRIO::create
    trio[2] := 1;
    #OUT + trio[2];        -- Prints out 1

See unnamedlink for more details on the section on operator redefinition.

## 6.2.2. Array Classes: Including AREF and calling new();

Sather permits the user to define array classes which support an array portion whose size is determined when the array is created. An object can have an array portion by including `AREF{T}`.

    class POLYGON is
       private include AREF{POINT}
          aget->private old_aget, aset->private old_aset;
             -- Rename aget and aset

       create(n_points:INT):SAME  is
          -- Create a new polygon with a 'n_points' points
          res:SAME := new(n_points);  -- Note that the new takes
          -- as argument of the size of the array
       end;

       aget(i:INT):POINT is
          if i > asize then raise "Not enough polygon points!" end;
          return old_aget(i);
       end;

       aset(i:INT, val:POINT) is
          if i > asize then raise "Not enough polygon points!" end;
          old_aset(i,val);
       end;
    end;

Since `AREF{T}` already defines `'aget'` and `'aset'` to do the right thing, we can provide wrappers around these routines to, for instance, provide an additional warning message. The above example makes use of the `POINT` class from unnamedlink. We could have also used the `PAIR` class defined on unnamedlink. The following example uses the polygon class to define a triangle.

    poly:POLYGON := #POLYGON(3);
    poly[0] := #POINT(3,4);
    poly[1] := #POINT(5,6);
    poly[2] := #POINT(0,0);

`AREF` defines several useful routines:

    asize:INT                        -- Returns the size of the array
    aelt!:T;                         -- Yields successive array elements
    aelt!(once beg:INT):T;           -- Yields elements from index 'beg'
    aelt!(once beg,once num:INT):T;  -- Yields 'num' elts from index 'beg'
    aelt!(once beg,once num,once step:INT):T;
       -- Yields 'num' elements, starting at index 'beg' with a 'step'
    ... Analgous versions of aset! ..
    acopy(src:SAME);                  -- Copy what fits from 'src' to self
    acopy(beg:INT,src:SAME);          -- Start copying into index 'beg'
    acopy(beg:INT,num:INT,src:SAME);
       -- Copy 'num' elements into self starting at index 'beg' of self
    aind!:INT;                         -- Yields successive array indices

When possible, use the above iterators since they are built-in and can be more efficient than other iterators.

## 6.2.3. Standard Arrays: ARRAY{T}

The class `ARRAY{T}` in the standard library is not a primitive data type. It is based on a built-in class `AREF{T}` which provides objects with an array portion. `ARRAY` obtains this functionality using an `include`, but chooses to modify the visibility of some of the methods. It also defines additional methods such a `contains`, `sort` etc. The methods `aget`, `aset` and `asize` are defined as `private` in `AREF`, but `ARRAY` redefines them to be public.

    class ARRAY{T} is
       private include AREF{T}
          -- Make these public.
          aget->aget,
          aset->aset,
          asize->asize;
       ...

       contains(e:T):BOOL is ... end
       ...
    end;

The array portion appears if there is an `include` path from the type to `AREF` for reference types or to `AVAL` for immutable types.

## Array Literals

Sather provides support for directly creating arrays from literal expressions

    a:ARRAY{INT} := |2,4,6,8|;
    b:ARRAY{STR} := |"apple","orange"|;

.

The type is taken to be the declared type of the context in which it appears and it must be `ARRAY{T}` for some type `T`. An array creation expression may not appear

- as the right hand side of a '`::=`' assignment

- as a method argument in which the overloading resolution is ambiguous

- as the left argument of the dot '`.`' operator.

      a:INT := |1,2,3|.size -- ILLEGAL

The types of each expression in the array literal must be subtypes of `T`. The size of the created array is equal to the number of specified expressions. The expressions in the literal are evaluated left to right and the results are assigned to successive array elements.

## 6.2.4. Multi-dimensional Arrays

Special support is neither present nor needed for multi-dimensional arrays. The `'aget'` and `'aset'` routines can take multiple arguments, thus permitting multiple indices. The library does provide `ARRAY2` and `ARRAY3` classes, which provide the necesary index computation. All standard array classes are addressed in row-major order. However, the MAT class is addressed in column major order for compatibility with external FORTRAN routines[1]. Multi-dimensonal array literals may be expressed by nesting of standard array literals

    a:ARRAY{ARRAY{INT}} := ||1,2,3|,|3,4,5|,|5,6,7||;

> [1] Efficiency in converting to FORTRAN was more important for mathematical entitites which will be used with existing mathematical libraries such as BLAS and LAPACK, most of which are in FORTRAN.

Prev | Home | Next
Parametrized Classes and Arrays | Up | Type Bounds