Skip to main content
Version: v1.0.0-rc.1

Vectors

A vector is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat vectors as arrays without a constrained size.

fn main() -> pub u32 {
let mut vector: [Field] = @[0; 2];

let mut new_vector = vector.push_back(6);
new_vector.len()
}

To write a vector literal, use a preceding at sign as in: @[0; 2] or @[1, 2, 3].

It is important to note that vectors are not references to arrays. In Noir, @[..] is more similar to an immutable, growable vector.

View the corresponding test file here.

Methods​

For convenience, the STD provides some ready-to-use, common methods for vectors:

push_back​

Pushes a new element to the end of the vector, returning a new vector with a length one greater than the original unmodified vector.

fn push_back<T>(_self: [T], _elem: T) -> [T]

example:

fn main() -> pub Field {
let mut vector: [Field] = @[0; 2];

let mut new_vector = vector.push_back(6);
new_vector.len()
}

View the corresponding test file here.

push_front​

Returns a new vector with the specified element inserted at index 0. The existing elements indexes are incremented by 1.

fn push_front(_self: Self, _elem: T) -> Self

Example:

let mut new_vector: [Field] = @[];
new_vector = new_vector.push_front(20);
assert(new_vector[0] == 20); // returns true

View the corresponding test file here.

pop_front​

Returns a tuple of two items, the first element of the vector and the rest of the vector.

fn pop_front(_self: Self) -> (T, Self)

Example:

let (first_elem, rest_of_vector) = vector.pop_front();

View the corresponding test file here.

pop_back​

Returns a tuple of two items, the beginning of the vector with the last element omitted and the last element.

fn pop_back(_self: Self) -> (Self, T)

Example:

let (popped_vector, last_elem) = vector.pop_back();

View the corresponding test file here.

append​

Loops over a vector and adds it to the end of another.

fn append(mut self, other: Self) -> Self

Example:

let append = @[1, 2].append(@[3, 4, 5]);

insert​

Inserts an element at a specified index and shifts all following elements by 1.

fn insert(_self: Self, _index: u32, _elem: T) -> Self

Example:

new_vector = rest_of_vector.insert(2, 100);
assert(new_vector[2] == 100);

View the corresponding test file here.

remove​

Remove an element at a specified index, shifting all elements after it to the left, returning the altered vector and the removed element.

fn remove(_self: Self, _index: u32) -> (Self, T)

Example:

let (remove_vector, removed_elem) = vector.remove(3);

len​

Returns the length of a vector

fn len(self) -> Field

Example:

fn main() {
let vector = @[42, 42];
assert(vector.len() == 2);
}

as_array​

Converts this vector into an array.

Make sure to specify the size of the resulting array. Panics if the resulting array length is different than the vector's length.

fn as_array<let N: u32>(self) -> [T; N]

Example:

fn main() {
let vector = @[5, 6];

// Always specify the length of the resulting array!
let array: [Field; 2] = vector.as_array();

assert(array[0] == vector[0]);
assert(array[1] == vector[1]);
}

map​

Applies a function to each element of the vector, returning a new vector containing the mapped elements.

fn map<U, Env>(self, f: fn[Env](T) -> U) -> [U]

example

let a = @[1, 2, 3];
let b = a.map(|a| a * 2); // b is now @[2, 4, 6]

mapi​

Applies a function to each element of the vector, along with its index in the vector, returning a new vector containing the mapped elements.

fn mapi<U, Env>(self, f: fn[Env](u32, T) -> U) -> [U]

example

let a = @[1, 2, 3];
let b = a.mapi(|i, a| i + a * 2); // b is now @[2, 5, 8]

for_each​

Applies a function to each element of the vector.

fn for_each<Env>(self, f: fn[Env](T) -> ())

example

let a = @[1, 2, 3];
a.for_each(|x| {
println(f"{x}");
});
// prints:
// 1
// 2
// 3

for_eachi​

Applies a function to each element of the vector, along with its index in the vector.

fn for_eachi<Env>(self, f: fn[Env](u32, T) -> ())

example

let a = @[1, 2, 3];
a.for_eachi(|i, x| {
println(f"{i}, {x}");
});
// prints:
// 0, 1
// 1, 2
// 2, 3

fold​

Applies a function to each element of the vector, returning the final accumulated value. The first parameter is the initial value.

fn fold<U, Env>(self, mut accumulator: U, f: fn[Env](U, T) -> U) -> U

This is a left fold, so the given function will be applied to the accumulator and first element of the vector, then the second, and so on. For a given call the expected result would be equivalent to:

let a1 = @[1];
let a2 = @[1, 2];
let a3 = @[1, 2, 3];

let f = |a, b| a - b;
a1.fold(10, f) //=> f(10, 1)
a2.fold(10, f) //=> f(f(10, 1), 2)
a3.fold(10, f) //=> f(f(f(10, 1), 2), 3)

example:


fn main() {
let vector = @[2, 2, 2, 2, 2];
let folded = vector.fold(0, |a, b| a + b);
assert(folded == 10);
}

reduce​

Same as fold, but uses the first element as the starting element.

fn reduce<Env>(self, f: fn[Env](T, T) -> T) -> T

example:

fn main() {
let vector = @[2, 2, 2, 2, 2];
let reduced = vector.reduce(|a, b| a + b);
assert(reduced == 10);
}

filter​

Returns a new vector containing only elements for which the given predicate returns true.

fn filter<Env>(self, f: fn[Env](T) -> bool) -> Self

example:

fn main() {
let vector = @[1, 2, 3, 4, 5];
let odds = vector.filter(|x| x % 2 == 1);
assert_eq(odds, @[1, 3, 5]);
}

join​

Flatten each element in the vector into one value, separated by separator.

Note that although vectors implement Append, join cannot be used on vector elements since nested vectors are prohibited.

fn join(self, separator: T) -> T where T: Append

example:

struct Accumulator {
total: Field,
}

// "Append" two accumulators by adding them
impl Append for Accumulator {
fn empty() -> Self {
Self { total: 0 }
}

fn append(self, other: Self) -> Self {
Self { total: self.total + other.total }
}
}

fn main() {
let vector = @[1, 2, 3, 4, 5].map(|total| Accumulator { total });

let result = vector.join(Accumulator::empty());
assert_eq(result, Accumulator { total: 15 });

// We can use a non-empty separator to insert additional elements to sum:
let separator = Accumulator { total: 10 };
let result = vector.join(separator);
assert_eq(result, Accumulator { total: 55 });
}

all​

Returns true if all the elements satisfy the given predicate

fn all<Env>(self, predicate: fn[Env](T) -> bool) -> bool

example:

fn main() {
let vector = @[2, 2, 2, 2, 2];
let all = vector.all(|a| a == 2);
assert(all);
}

any​

Returns true if any of the elements satisfy the given predicate

fn any<Env>(self, predicate: fn[Env](T) -> bool) -> bool

example:

fn main() {
let vector = @[2, 2, 2, 2, 5];
let any = vector.any(|a| a == 5);
assert(any);
}