Search results

There are no results.

std.array.Array

type pub Array[T]

An ordered, integer-indexed generic collection of values.

Accessing values in an Array is a constant-time operation.

Arrays are created using the array literal syntax, instead of using a method. Here's how you'd create an empty Array:

[]

And here's how you'd create an Array with values:

[10, 20, 30]

All values in an array must be of the same type, and the array's value type is based on the type of the first value.

Static methods

filled

Show source code
Hide source code
fn pub static filled[V: Clone](with: move V, times: Int) -> Array[move V] {
  if times == 0 { return [] }

  let array = with_capacity(times)
  let temp = ref with

  (times - 1).times(fn (_) { array.push(temp.clone) })
  array.push(with)
  array
}
fn pub static filled[V: Clone](with: move V, times: Int) -> Array[move V]

Returns an array filled with a certain amount of values.

The times argument specifies how many times the with argument must exist in the array.

Examples

Array.filled(with: 0, times: 4) # => [0, 0, 0, 0]

with_capacity

Show source code
Hide source code
fn pub static with_capacity(size: Int) -> Array[T] {
  if size < 0 { invalid_capacity(size) }

  Array(size: 0, capacity: size, buffer: alloc.resize(0 as Pointer[T], size))
}
fn pub static with_capacity(size: Int) -> Array[T]

Returns a new Array with enough space for at least size values.

Panics

This method panics of size if less than zero.

Instance methods

!=

Show source code
Hide source code
fn pub !=(other: ref Self) -> Bool {
  (self == other).false?
}
fn pub !=(other: ref Self) -> Bool
if
  T: Equal

Returns true if self and the given object are not equal to each other.

==

Show source code
Hide source code
fn pub ==(other: ref Array[T]) -> Bool {
  if @size != other.size { return false }

  let mut index = 0
  let max = @size

  while index < max {
    let ours = get(index)
    let theirs = other.get(index)

    if ours != theirs { return false }

    index += 1
  }

  true
}
fn pub ==(other: ref Array[T]) -> Bool
if
  T: Equal

Returns true if self and the given Array are identical.

Examples

Comparing two identical arrays:

[10, 20, 30] == [10, 20, 30] # => true

Comparing two arrays with a different size:

[10] == [10, 20] # => false

Comparing two arrays with the same size but with different values:

[10, 20] == [20, 10] # => false

append

Show source code
Hide source code
fn pub mut append(other: Array[T]) {
  let len = other.size

  if len == 0 { return }

  reserve_exact(len)

  let tail = ptr.add(@buffer, @size)

  alloc.copy(other.pointer, tail, len)
  @size += len

  # This is necessary such that when `other` is dropped, we don't drop the
  # values that have been moved into `self`.
  other.size = 0
}
fn pub mut append(other: Array[T])

Appends the values of the given Array to self.

Examples

Appending one Array to another:

let numbers = [10, 20, 30]

numbers.append([40, 50])

numbers.size # => 5

capacity

Show source code
Hide source code
fn pub capacity -> Int {
  @capacity
}
fn pub capacity -> Int

Returns the number of values that can be stored in self before self needs to be resized.

Examples

Array.with_capacity(2).capacity # => 2

clear

Show source code
Hide source code
fn pub mut clear {
  let mut index = 0
  let max = @size

  while index < max { read_from(index := index + 1) }

  @size = 0
}
fn pub mut clear

Removes all values in the Array.

Examples

let array = [10, 20, 30]

array.clear
array.empty? # => true

clone

Show source code
Hide source code
fn pub clone -> Array[move T] {
  let len = @size
  let new = Array.with_capacity(len)
  let mut index = 0

  while index < len { new.push(get_unchecked(index := index + 1).clone) }

  new
}
fn pub clone -> Array[move T]
if
  T: Clone

Creates a clone of self.

The returned value is an owned value that is the same type as the receiver of this method. For example, cloning a ref Array[Int] results in a Array[Int], not another ref Array[Int].

contains?

Show source code
Hide source code
fn pub contains?(value: ref T) -> Bool {
  iter.any?(fn (ours) { ours == value })
}
fn pub contains?(value: ref T) -> Bool
if
  T: Equal

Returns true if self contains the given value.

Examples

[10, 20, 30].contains?(10) # => true

empty?

Show source code
Hide source code
fn pub empty? -> Bool {
  @size == 0
}
fn pub empty? -> Bool

Returns true if self is empty.

Examples

[10].empty? # => false
[].empty?   # => true

fmt

Show source code
Hide source code
fn pub fmt(formatter: mut Formatter) {
  let fmt = formatter.array

  for value in iter { fmt.value(value) }

  fmt.finish
}
fn pub fmt(formatter: mut Formatter)
if
  T: Format

Formats self in a human-readable format for debugging purposes.

get

Show source code
Hide source code
fn pub inline get(index: Int) -> Result[ref T, OutOfBounds] {
  try check_bounds(index, @size)
  Result.Ok(get_unchecked(index))
}
fn pub inline get(index: Int) -> Result[ref T, OutOfBounds]

Returns an immutable borrow of the value at the given index.

If the index is out of bounds, a std.bounds.OutOfBounds error is returned.

Examples

let numbers = [10, 20]

numbers.get(0)  # => Result.Ok(10)
numbers.get(10) # => Result.Error(OutOfBounds(...))

get_mut

Show source code
Hide source code
fn pub inline mut get_mut(index: Int) -> Result[mut T, OutOfBounds] {
  try check_bounds(index, @size)
  Result.Ok(get_unchecked_mut(index))
}
fn pub inline mut get_mut(index: Int) -> Result[mut T: mut, OutOfBounds]
if
  T: mut

Returns a mutable borrow of the value at the given index.

If the index is out of bounds, a std.bounds.OutOfBounds error is returned.

Examples

let numbers = [10, 20]

numbers.get_mut(0)  # => Result.Ok(10)
numbers.get_mut(10) # => Result.Error(OutOfBounds(...))

hash

Show source code
Hide source code
fn pub hash[H: mut + Hasher](hasher: mut H) {
  let mut index = 0
  let len = @size

  while index < len { get_unchecked(index := index + 1).hash(hasher) }
}
fn pub hash[H: mut + Hasher](hasher: mut H: mut)
if
  T: Hash

Writes the hash for self into the given Hasher.

index_of

Show source code
Hide source code
fn pub index_of(value: ref T) -> Option[Int] {
  let mut idx = 0

  while idx < @size {
    if get_unchecked(idx) == value { return Option.Some(idx) }

    idx += 1
  }

  Option.None
}
fn pub index_of(value: ref T) -> Option[Int]
if
  T: Equal

Returns the index of value as a Some if present, otherwise it returns a None.

Examples

[10, 20, 30].index_of(20) # => Option.Some(1)
[10, 20, 30].index_of(50) # => Option.None

insert

Show source code
Hide source code
fn pub mut insert(index: Int, value: T) {
  if index < 0 or index > @size {
    panic(OutOfBounds.new(index, @size).to_string)
  }

  reserve(1)

  # Shift to the right if the insertion isn't at the end of the array. If we
  # have values like this:
  #
  #     [A, B, C, D]
  #
  # And we want to insert at the index of B (index 1), this results in the
  # following values:
  #
  #     [A, B, B, C, D]
  #
  # We can then overwrite index 1 with the value to insert.
  if index < @size {
    let from = address_of(index)
    let to = address_of(index + 1)

    alloc.copy(from, to, size: @size - index)
  }

  write_to(index, value)
  @size += 1
}
fn pub mut insert(index: Int, value: T)

Inserts the value at the given index, shifting all values after it to the right.

Panics

This method panics if index is out of bounds.

Examples

Inserting a value at the start:

let nums = [10, 20]

nums.insert(0, 30)
nums # => [30, 10, 20]

Inserting a value at the end:

let nums = [10, 20]

nums.insert(2, 30)
nums # => [10, 20, 30]

into_iter

Show source code
Hide source code
fn pub move into_iter -> IntoIter[T] {
  IntoIter(array: self, index: 0)
}
fn pub move into_iter -> IntoIter[T]

Returns an iterator that moves the values out of self.

Examples

let numbers = [10, 20, 30]
let iter = numbers.into_iter

iter.next # => Option.Some(10)
iter.next # => Option.Some(20)
iter.next # => Option.Some(30)
iter.next # => Option.None

iter

Show source code
Hide source code
fn pub iter -> Stream[ref T] {
  let mut idx = 0

  Stream.new(fn move {
    if idx < @size {
      Option.Some(get_unchecked(idx := idx + 1))
    } else {
      Option.None
    }
  })
}
fn pub iter -> Stream[ref T]

Returns an iterator that yields immutable references to the values in self.

iter_mut

Show source code
Hide source code
fn pub mut iter_mut -> Stream[mut T] {
  let mut idx = 0

  Stream.new(fn move {
    if idx < @size {
      Option.Some(get_unchecked_mut(idx := idx + 1))
    } else {
      Option.None
    }
  })
}
fn pub mut iter_mut -> Stream[mut T: mut]
if
  T: mut

Returns an iterator that yields mutable references to the values in self.

last

Show source code
Hide source code
fn pub last -> Option[ref T] {
  get(size - 1).ok
}
fn pub last -> Option[ref T]

Returns an immutable reference to the last value in self.

Examples

[].last       # => Option.None
[10, 20].last # => Option.Some(20)

last_mut

Show source code
Hide source code
fn pub mut last_mut -> Option[mut T] {
  get_mut(size - 1).ok
}
fn pub mut last_mut -> Option[mut T: mut]
if
  T: mut

Returns a mutable reference to the last value in self.

Examples

[].last_mut       # => Option.None
[10, 20].last_mut # => Option.Some(20)

pop

Show source code
Hide source code
fn pub mut pop -> Option[T] {
  if @size == 0 { return Option.None }

  @size -= 1
  Option.Some(read_from(@size))
}
fn pub mut pop -> Option[T]

Removes a value from the back of the Array, returning the removed value.

If no value was found, a None is returned instead.

Examples

Popping an existing value:

let array = [10]

array.pop    # => Option.Some(10)
array.empty? # => true

Popping a value when the Array is empty:

let array = []

array.pop # => Option.None

push

Show source code
Hide source code
fn pub mut push(value: T) {
  reserve(1)
  write_to(@size, value)
  @size += 1
}
fn pub mut push(value: T)

Pushes a value to the back of the Array.

Examples

Pushing a value into an Array:

let array = []

array.push(10) # => Nil
array.get(0)   # => 10

remove_at

Show source code
Hide source code
fn pub mut remove_at(index: Int) -> Result[T, OutOfBounds] {
  let len = size

  try check_bounds(index, len)

  let addr = address_of(index)
  let val = addr.0

  alloc.copy(from: ptr.add(addr, 1), to: addr, size: len - index - 1)
  @size = len - 1
  Result.Ok(val)
}
fn pub mut remove_at(index: Int) -> Result[T, OutOfBounds]

Removes the value at the given index, returning the removed value.

Values to the right of the index are shifted to the left.

If the index is out of bounds, a std.bounds.OutOfBounds error is returned.

Examples

Removing an existing value will result in the value being removed from the Array and returned:

let array = [10]

array.remove_at(0) # => Result.Ok(10)
array.empty?       # => true

remove_if

Show source code
Hide source code
fn pub mut remove_if(condition: fn (ref T) -> Bool) {
  let mut idx = 0

  while idx < @size {
    if condition.call(get_unchecked(idx)) {
      let addr = address_of(idx)

      drop_value(addr.0)
      alloc.copy(from: ptr.add(addr, 1), to: addr, size: @size - idx - 1)
      @size -= 1

      # Because we shift to the left, we need to visit the current index
      # again, otherwise we'd miss the value that came after it _before_ the
      # shift.
    } else {
      idx += 1
    }
  }
}
fn pub mut remove_if(condition: fn (ref T) -> Bool)

Removes all values for which the condition closure returns true.

This method shifts values to the left every time a value is removed. When removing many values from an Array, it's likely more efficient to create a new Array and copy/move the values to keep to this new Array.

Examples

let vals = [10, 20, 30, 40, 50]

vals.remove_if(fn (v) { v <= 30 })
vals # => [40, 50]

reserve

Show source code
Hide source code
fn pub mut reserve(size: Int) {
  if @capacity - @size >= size { return }

  @capacity = max(@capacity * 2, @capacity + size)
  @buffer = alloc.resize(@buffer, @capacity)
}
fn pub mut reserve(size: Int)

Reserves space for size additional values.

The actual space reserved may be greater to prevent frequent reallocations. After calling this method, the capacity will be greater than or equal to self.size + size.

If the capacity is great enough or the given size is less than zero, this method does nothing.

reserve_exact

Show source code
Hide source code
fn pub mut reserve_exact(size: Int) {
  if @capacity - @size >= size { return }

  @capacity = @capacity + size
  @buffer = alloc.resize(@buffer, @capacity)
}
fn pub mut reserve_exact(size: Int)

Reserves space for exactly size additional values.

Unlike Array.reserve, this method won't allocate more than the given amount.

If there's already enough space for size extra values, this method does nothing.

reverse

Show source code
Hide source code
fn pub mut reverse {
  let mut a = 0
  let mut b = @size - 1

  while a < b {
    let a_val = read_from(a)
    let b_val = read_from(b)

    write_to(b, a_val)
    write_to(a, b_val)
    a += 1
    b -= 1
  }
}
fn pub mut reverse

Reverses self in-place

Examples

let a = [10, 20, 30]

a.reverse

a # => [30, 20, 10]

reverse_iter

Show source code
Hide source code
fn pub reverse_iter -> Stream[ref T] {
  let mut index = size - 1

  Stream.new(fn move {
    if index > -1 { get(index := index - 1).ok } else { Option.None }
  })
}
fn pub reverse_iter -> Stream[ref T]

Returns an Iter that iterates over all values in self in reverse order.

Examples

Iterating over an Array in reverse order:

let numbers = [10, 20, 30]
let iter = numbers.reverse_iter

iter.next # => Option.Some(30)
iter.next # => Option.Some(20)
iter.next # => Option.Some(10)
iter.next # => Option.None

set

Show source code
Hide source code
fn pub mut set(index: Int, value: T) {
  check_bounds(index, @size).or_panic
  drop_value(read_from(index))
  write_to(index, value)
}
fn pub mut set(index: Int, value: T)

Stores a value at the given index.

If a value is already present at the given index, it's dropped before the new value overwrites it.

Panics

This method panics if the index is out of bounds.

Examples

let array = []

array.set(0, 10)
array # => [10]

shuffle

Show source code
Hide source code
fn pub mut shuffle(rng: mut Random) {
  let mut swap = size - 1

  while swap > 0 {
    swap_indexes(swap, with: rng.int_between(min: 0, max: swap))
    swap -= 1
  }
}
fn pub mut shuffle(rng: mut Random)

Sorts the values in self such that they are in a random order.

The algorithm used by this method is Sattolo's algorithm. Some more details on this are found here:

Examples

import std.rand (Random)

let rng = Random.new
let nums = [10, 20]

nums.shuffle(rng)
nums # => [20, 10]

size

Show source code
Hide source code
fn pub size -> Int {
  @size
}
fn pub size -> Int

Returns the number of values in self.

Examples

Getting the size of an empty Array:

[].size # => 0

Getting the size of an Array with values:

[10].size # => 1

sort

Show source code
Hide source code
fn pub mut sort {
  stable_sort(self, fn (a, b) { a <= b })
}
fn pub mut sort
if
  T: Compare

Sorts the values in self in ascending order.

This method performs a stable sort, meaning it maintains the relative order of duplicate values.

Examples

let nums = [0, 3, 3, 5, 9, 1]

nums.sort
nums # => [0, 1, 3, 3, 5, 9]

sort_by

Show source code
Hide source code
fn pub mut sort_by(block: fn (ref T, ref T) -> Ordering) {
  stable_sort(self, fn (a, b) {
    match block.call(a, b) {
      case Less or Equal -> true
      case _ -> false
    }
  })
}
fn pub mut sort_by(block: fn (ref T, ref T) -> Ordering)

Sorts the values in self using a custom comparison closure.

Like Array.sort, this method performs a stable sort.

Examples

let nums = [0, 3, 3, 5, 9, 1]

nums.sort_by fn (a, b) { b.cmp(a) }
nums # => [9, 5, 3, 3, 1, 0]

swap

Show source code
Hide source code
fn pub mut swap(index: Int, with: T) -> T {
  check_bounds(index, @size).or_panic

  let old = read_from(index)

  write_to(index, with)
  old
}
fn pub mut swap(index: Int, with: T) -> T

Inserts the value at the given index, returning the old value.

Panics

This method panics if the index is out of bounds.

Examples

let numbers = [10, 20, 30]

numbers.swap(index: 1, with: 40) # => 20
numbers                          # => [10, 40, 30]

swap_indexes

Show source code
Hide source code
fn pub mut swap_indexes(index: Int, with: Int) {
  check_bounds(index, @size).or_panic
  check_bounds(with, @size).or_panic

  let a = read_from(index)
  let b = read_from(with)

  write_to(index, b)
  write_to(with, a)
}
fn pub mut swap_indexes(index: Int, with: Int)

Swaps the values at the given indexes.

Panics

This method panics if index or with is out of bounds.

Examples

let numbers = [10, 20, 30]

numbers.swap_indexes(index: 0, with: 2)

numbers # => [30, 20, 10]

Implemented traits

std.clone.

Clone

impl Clone for Array
if
  T: Clone
std.cmp.

Equal

impl Equal for Array
if
  T: Equal
std.drop.

Drop

impl Drop for Array
std.fmt.

Format

impl Format for Array
if
  T: Format
std.hash.

Hash

impl Hash for Array
if
  T: Hash