7.9. Vectors

Vectors are language supported objects that allow for dynamically sized arrays. Once created, vectors in Gazprea behave exactly like arrays: they can be intermixed with arrays in expressions; they can be used on the RHS of array declarations and initializations; and they can be passed as array arguments to subroutines and functions.

7.9.1. Declaration

Vectors are declared and (optionally) initialized as follows. (Note that we have replaced <> with | in the notation below since the literals < and > are used in the declaration)

vector<|type|> |identifier|;
vector<|type|> |identifier| = |type-expr|;
vector<|type|> |identifier| = |type-array|;

Unlike the array type, Gazprea vectors do not have an explicit size specifier, often called capacity in other languages. Below are some examples of vector declarations.

const vector<integer[2]> v1 = 3;       // [[3, 3]]
const vector<integer[2]> v2 = [4, 5];  // [[4, 5]]
const vector<integer> v3 = 42;         // [42]
const vector<real> v4 = 1;             // [1.0]

Vectors of inferred sized arrays assume the size of the first array in the vector. Subsequent array elements of less than the inferred size are padded. Those greater raise a runtime SizeError.

const vector<character> vec = ['a', 'b', 'c'];
const vector<real[*]> ragged_right = [[1.0], [2.0, 2.0]]; // SizeError
const vector<real[*]> paddeded_right = [[1.0, 2.0], [1.0]]; // Padds second element
const vector<character> const_vec = vec;

7.9.2. Operations

Operations on vectors are identical syntactically and semantically to operations on arrays. In particular, operand lengths must match for binary expressions and dot product. Vectors can behave as arrays by using slices:

var vector<integer> v1, v2;
var integer[3] a;
v1.append([1, 2, 3]);
a = v1; // slice of v yields array and can be used to initialize 'a'
v2 = v1 + a; // slice of vector plus array yields result type array
a = v1 + v2; // slice of v1 + slice of v2 still yields array type

A vector or vector slice can be passed as a call argument that has been declared as an array slice of the same size and type. When indexing a vector of arrays, the first index selects the array element within the vector, and the second index selects the element within the array:

vector<real[*]> ragged_right = [[1.0], [2.1]];
length(ragged_right[1]) -> std_output; // prints 1
ragged_right[2][1] -> std_output; // prints 2.1

As a language supported object, Gazprea provides several methods for vector:

  • push() - pushes a new element to the back of the vector

  • len() - number of elements in the vector

  • append(T[*]) - append another array slice to the vector where T is the type of the original vector or a type that can be implicitly cast to it. The following example tracks the elements inside vec through various appends.

    const x = 1..10;
    var vector<real[2]> vec;       // []
    
    // scalar to array promotion
    vec.append(1);                 // [[1.0, 1.0]]
    
    // array padding
    vec.append(3..3);              // [[1,0, 1.0], [3.0, 0.0]]
    
    // slices
    vec.append(x[5..7]);           // [[1,0, 1.0], [3.0, 0.0], [5.0, 6.0]]
    
    vec[tvec.len()] -> std_output; // prints 3