16 Vectors
The builtin vector type provides a simple but powerful abstraction for creating collections of objects of the same type. In terms of functionality, a vector is close to plain arrays as defined in most programming languages. Vectors implement the iterable protocol so they can be iterated with a for
syntax.
Vectors in HULK can be defined with two different syntactic forms: explicit and implicit.
16.1 Explicit syntax
An explicit vector of Number
, for example, can be defined as follows:
let numbers = [1,2,3,4,5,6,7,8,9] in
for (x in numbers)
print(x);
Because vectors implement the iterable protocol, you can explicitely find a next
and current
methods in case you ever need them. Besides that, vectors also have a size(): Number
method that returns the number of items in the vector.
Vectors also support an indexing syntax using square brackets []
, as in the following example:
let numbers = [1,2,3,4,5,6,7,8,9] in print(numbers[7]);
16.2 Implicit syntax
An implicit vector can be created using what we call a generator pattern, which is always an expression.
Here’s one example:
let squares = [x^2 | x in range(1,10)] in print(x);
// prints 2, 4, 6, 8, 10, ...
In general, the syntax has the form [<expr> | <symbol> in <iterable>]
, where <expr>
is run in a new scope where symbol
is iteratively bound to each element in the vector.
16.3 Typing vectors
Since vectors are iterables, you can safely pass a vector as argument to method that expects an iterable:
function sum(numbers: Number*): Number =>
let total = 0 in
for (x in numbers)
:= total + x;
total
let numbers = [1,2,3,4,5] in
print(sum(numbers));
However, inside sum
you cannot use the indexing operator []
or the size
method, because the argument is typed as an iterable, and not explicitly as a vector. To fix this, HULK provides another special syntax for vectors, using the T[]
notation:
function mean(numbers: Number[]): Number =>
let total = 0 in {
for (x in numbers)
total := total + x;
// here `numbers` is known to be vector
/ numbers.size();
total ;
}
let numbers = [1,2,3,4,5] in
print(mean(numbers));
Like with iterables, what happens under the hood is that the compiler implicitely defines a type with the following structure:
type Vector_T {size() {
// impementation of size ...
}
iter(): Iterable_T {
// implementation of iter
} }