Indexable(T) - Crystal 1.13.1

# module Indexable(T)

##
Overview

A container that allows accessing elements via a numeric index.

Indexing starts at `0`. A negative index is assumed to be relative to the end of the container: `-1` indicates the last element, `-2` is the next to last element, and so on.

Types including this module are typically `Array`-like types.

##
Stability guarantees

Several methods in `Indexable`, such as `#bsearch` and `#cartesian_product`, require the collection to be stable; that is, calling `#each(&)` over and over again should always yield the same elements, provided the collection is not mutated between the calls. In particular, `#each(&)` itself should not mutate the collection throughout the loop. Stability of an `Indexable` is guaranteed if the following criteria are met:

- `#unsafe_fetch` and `#size` do not mutate the collection
- `#each(&)` and `#each_index(&)` are not overridden

The standard library assumes that all including types of `Indexable` are always stable. It is undefined behavior to implement an `Indexable` that is not stable or only conditionally stable.

##
Included Modules

- Enumerable(T)
- Iterable(T)

##
Direct including types

- Indexable::Mutable(T)
- LLVM::ParameterCollection
- Tuple(*T)

##
Defined in:

indexable.cr

##
Class Method Summary

- .cartesian_product(indexables : Indexable(Indexable))

  Returns an `Array` of all ordered combinations of elements taken from each of the indexables as `Array`s.

- .each_cartesian(indexables : Indexable(Indexable), reuse = false, &)

  Yields each ordered combination of the elements taken from each of the indexables as `Array`s.

- .each_cartesian(indexables : Indexable(Indexable), reuse = false)

  Returns an iterator that enumerates the ordered combinations of elements taken from the indexables as `Array`s.

##
Instance Method Summary

- #[](index : Int)

  Returns the element at the given index.

- #[]?(index : Int)

  Returns the element at the given index.

- #bsearch(& : T -> _)

  By using binary search, returns the first element for which the passed block returns a truthy value.

- #bsearch_index(& : T, Int32 -> _)

  By using binary search, returns the index of the first element for which the passed block returns a truthy value.

- #cartesian_product(*others : Indexable)

  Returns an `Array` of all ordered combinations of elements taken from each of `self` and others as `Tuple`s.

- #combinations(size : Int = self.size)

  Returns an `Array` with all possible combinations of size of `self`.

- #dig(index : Int, *subindexes)

  Traverses the depth of a structure and returns the value, otherwise raises `IndexError`.

- #dig?(index : Int, *subindexes)

  Traverses the depth of a structure and returns the value.

- #each(& : T -> )

  Calls the given block once for each element in `self`, passing that element as a parameter.

- #each

  Returns an `Iterator` for the elements of `self`.

- #each(*, start : Int, count : Int, & : T -> )

  Calls the given block once for `count` number of elements in `self` starting from index `start`, passing each element as a parameter.

- #each(*, within range : Range, & : T -> )

  Calls the given block once for all elements at indices within the given `range`, passing each element as a parameter.

- #each_cartesian(*others : Indexable, &)

  Yields each ordered combination of the elements taken from each of `self` and others as a `Tuple`.

- #each_cartesian(*others : Indexable)

  Returns an iterator that enumerates the ordered combinations of elements taken from each of `self` and others as `Tuple`s.

- #each_combination(size : Int = self.size, reuse = false, &) : Nil

  Yields each possible combination of size of `self`.

- #each_combination(size : Int = self.size, reuse = false)

  Returns an `Iterator` over each possible combination of size of `self`.

- #each_index(& : Int32 -> ) : Nil

  Calls the given block once for each index in `self`, passing that index as a parameter.

- #each_index

  Returns an `Iterator` for each index in `self`.

- #each_index(*, start : Int, count : Int, &)

  Calls the given block once for `count` number of indices in `self` starting from index `start`, passing each index as a parameter.

- #each_permutation(size : Int = self.size, reuse = false, &) : Nil

  Yields each possible permutation of size of `self`.

- #each_permutation(size : Int = self.size, reuse = false)

  Returns an `Iterator` over each possible permutation of size of `self`.

- #each_repeated_combination(size : Int = self.size, reuse = false, &) : Nil

  Yields each possible combination with repeated elements of size of `self`.

- #each_repeated_combination(size : Int = self.size, reuse = false)

  Returns an `Iterator` over each possible combination with repeated elements of size of `self`.

- #empty? : Bool

  Returns `true` if `self` is empty, `false` otherwise.

- #equals?(other : Indexable, &) : Bool

  Optimized version of `#equals?` used when `other` is also an `Indexable`.

- #equals?(other, &)

  Determines if `self` equals other according to a comparison done by the given block.

- #fetch(index : Int, &)

  Returns the element at the given index, if in bounds, otherwise executes the given block with the index and returns its value.

- #fetch(index, default)

  Returns the value at the index given by index, or when not found the value given by default.

- #first(&)

  Returns the first element in the collection, If the collection is empty, calls the block and returns its value.

- #hash(hasher)

  See `Object#hash(hasher)`

- #index(object, offset : Int = 0)

  Returns the index of the first appearance of object in `self` starting from the given offset, or `nil` if object is not in `self`.

- #index(offset : Int = 0, & : T -> )

  Returns the index of the first object in `self` for which the block is truthy, starting from the given offset, or `nil` if no match is found.

- #index!(obj, offset : Int = 0)

  Returns the index of the first appearance of obj in `self` starting from the given offset.

- #index!(offset : Int = 0, & : T -> )

  Returns the index of the first object in `self` for which the block is truthy, starting from the given offset.

- #join(separator : String | Char | Number = "") : String

  Optimized version of `Enumerable#join` that performs better when all of the elements in this indexable are strings: the total string bytesize to return can be computed before creating the final string, which performs better because there's no need to do reallocations.

- #last : T

  Returns the last element of `self` if it's not empty, or raises `IndexError`.

- #last(&)

  Returns the last element of `self` if it's not empty, or the given block's value.

- #last? : T | Nil

  Returns the last element of `self` if it's not empty, or `nil`.

- #permutations(size : Int = self.size) : Array(Array(T))

  Returns an `Array` with all possible permutations of size of `self`.

- #repeated_combinations(size : Int = self.size) : Array(Array(T))

  Returns an `Array` with all possible combinations with repeated elements of size of `self`.

- #reverse_each(& : T -> ) : Nil

  Same as `#each`, but works in reverse.

- #reverse_each

  Returns an `Iterator` over the elements of `self` in reverse order.

- #rindex(value, offset = size - 1)

  Returns the index of the last appearance of value in `self`, or `nil` if the value is not in `self`.

- #rindex(offset = size - 1, & : T -> )

  Returns the index of the first object in `self` for which the block is truthy, starting from the last object, or `nil` if no match is found.

- #rindex!(value, offset = size - 1)

  Returns the index of the last appearance of value in `self`, or `nil` if the value is not in `self`.

- #rindex!(offset = size - 1, & : T -> )

  Returns the index of the first object in `self` for which the block is truthy, starting from the last object, or `nil` if no match is found.

- #sample(n : Int, random : Random = Random::DEFAULT) : Array(T)

  Returns an `Array` of n random elements from `self`, using the given random number generator.

- #sample(random : Random = Random::DEFAULT)

  Optimized version of `Enumerable#sample` that runs in O(1) time.

- #size

  Returns the number of elements in this container.

- #to_a : Array(T)

  Returns an `Array` with all the elements in the collection.

- #to_a(& : T -> U) : Array(U) forall U

  Returns an `Array` with the results of running block against each element of the collection.

- #unsafe_fetch(index : Int)

  Returns the element at the given index, without doing any bounds check.

- #values_at(*indexes : Int)

  Returns a `Tuple` populated with the elements at the given indexes.

### Instance methods inherited from module `Enumerable(T)`

accumulate(initial : U) : Array(U) forall U
accumulate : Array(T)
accumulate(initial : U, &block : U, T -> U) : Array(U) forall U
accumulate(&block : T, T -> T) : Array(T) accumulate, all?(& : T -> ) : Bool
all?(pattern) : Bool
all? : Bool all?, any?(& : T -> ) : Bool
any?(pattern) : Bool
any? : Bool any?, chunks(&block : T -> U) forall U chunks, compact_map(& : T -> _) compact_map, count(& : T -> ) : Int32
count(item) : Int32 count, cycle(n, & : T -> ) : Nil
cycle(& : T -> ) : Nil cycle, each(& : T -> ) each, each_cons(count : Int, reuse = false, &) each_cons, each_cons_pair(& : T, T -> ) : Nil each_cons_pair, each_slice(count : Int, reuse = false, &) each_slice, each_step(n : Int, *, offset : Int = 0, & : T -> ) : Nil each_step, each_with_index(offset = 0, &) each_with_index, each_with_object(obj : U, & : T, U -> ) : U forall U each_with_object, empty? : Bool empty?, find(if_none = nil, & : T -> ) find, find!(& : T -> ) : T find!, first(&)
first(count : Int) : Array(T)
first : T first, first? : T | Nil first?, flat_map(& : T -> _) flat_map, group_by(& : T -> U) forall U group_by, in_groups_of(size : Int, filled_up_with : U = nil) forall U
in_groups_of(size : Int, filled_up_with : U = nil, reuse = false, &) forall U in_groups_of, in_slices_of(size : Int) : Array(Array(T)) in_slices_of, includes?(obj) : Bool includes?, index(& : T -> ) : Int32 | Nil
index(obj) : Int32 | Nil index, index!(& : T -> ) : Int32
index!(obj) : Int32 index!, index_by(& : T -> U) : Hash(U, T) forall U index_by, join(io : IO, separator = "") : Nil
join(separator, io : IO) : Nil
join(separator = "") : String
join(io : IO, separator = "", & : T, IO -> )
join(separator, io : IO, &)
join(separator = "", & : T -> ) join, map(& : T -> U) : Array(U) forall U map, map_with_index(offset = 0, & : T, Int32 -> U) : Array(U) forall U map_with_index, max(count : Int) : Array(T)
max : T max, max? : T | Nil max?, max_by(& : T -> U) : T forall U max_by, max_by?(& : T -> U) : T | Nil forall U max_by?, max_of(& : T -> U) : U forall U max_of, max_of?(& : T -> U) : U | Nil forall U max_of?, min(count : Int) : Array(T)
min : T min, min? : T | Nil min?, min_by(& : T -> U) : T forall U min_by, min_by?(& : T -> U) : T | Nil forall U min_by?, min_of(& : T -> U) : U forall U min_of, min_of?(& : T -> U) : U | Nil forall U min_of?, minmax : Tuple(T, T) minmax, minmax? : Tuple(T | Nil, T | Nil) minmax?, minmax_by(& : T -> U) : Tuple(T, T) forall U minmax_by, minmax_by?(& : T -> U) : Tuple(T, T) | Tuple(Nil, Nil) forall U minmax_by?, minmax_of(& : T -> U) : Tuple(U, U) forall U minmax_of, minmax_of?(& : T -> U) : Tuple(U, U) | Tuple(Nil, Nil) forall U minmax_of?, none?(& : T -> ) : Bool
none?(pattern) : Bool
none? : Bool none?, one?(& : T -> ) : Bool
one?(pattern) : Bool
one? : Bool one?, partition(& : T -> ) : Tuple(Array(T), Array(T))
partition(type : U.class) forall U partition, present? : Bool present?, product(initial : Number)
product
product(initial : Number, & : T -> )
product(& : T -> _) product, reduce(memo, &)
reduce(&) reduce, reduce?(&) reduce?, reject(& : T -> )
reject(type : U.class) forall U
reject(pattern) : Array(T) reject, sample(n : Int, random : Random = Random::DEFAULT) : Array(T)
sample(random : Random = Random::DEFAULT) : T sample, select(& : T -> )
select(type : U.class) : Array(U) forall U
select(pattern) : Array(T) select, size : Int32 size, skip(count : Int) skip, skip_while(& : T -> ) : Array(T) skip_while, sum(initial)
sum
sum(initial, & : T -> )
sum(& : T -> ) sum, take_while(& : T -> ) : Array(T) take_while, tally(hash)
tally : Hash(T, Int32) tally, tally_by(hash, &)
tally_by(&block : T -> U) : Hash(U, Int32) forall U tally_by, to_a : Array(T)
to_a(& : T -> U) : Array(U) forall U to_a, to_h
to_h(& : T -> Tuple(K, V)) forall K, V to_h, to_set : Set(T)
to_set(&block : T -> U) : Set(U) forall U to_set, zip(*others : Indexable | Iterable | Iterator, &)
zip(*others : Indexable | Iterable | Iterator) zip, zip?(*others : Indexable | Iterable | Iterator, &)
zip?(*others : Indexable | Iterable | Iterator) zip?

### Class methods inherited from module `Enumerable(T)`

element_type(x) element_type

### Instance methods inherited from module `Iterable(T)`

chunk(reuse = false, &block : T -> U) forall U chunk, chunk_while(reuse : Bool | Array(T) = false, &block : T, T -> B) forall B chunk_while, cycle(n)
cycle cycle, each each, each_cons(count : Int, reuse = false) each_cons, each_cons_pair each_cons_pair, each_slice(count : Int, reuse = false) each_slice, each_step(n : Int)
each_step(n : Int, *, offset : Int) each_step, each_with_index(offset = 0) each_with_index, each_with_object(obj) each_with_object, slice_after(reuse : Bool | Array(T) = false, &block : T -> B) forall B
slice_after(pattern, reuse : Bool | Array(T) = false) slice_after, slice_before(reuse : Bool | Array(T) = false, &block : T -> B) forall B
slice_before(pattern, reuse : Bool | Array(T) = false) slice_before, slice_when(reuse : Bool | Array(T) = false, &block : T, T -> B) forall B slice_when

##
Class Method Detail

def self.cartesian_product(indexables : Indexable(Indexable)) #

Returns an `Array` of all ordered combinations of elements taken from each of the indexables as `Array`s. Traversal of elements starts from the last `Indexable`. If indexables is empty, the returned product contains exactly one empty `Array`.

`#cartesian_product` is preferred over this class method when the quantity of indexables is known in advance.

    Indexable.cartesian_product([[1, 2, 3], [4, 5]]) # => [[1, 4], [1, 5], [2, 4], [2, 5], [3, 4], [3, 5]]

def self.each_cartesian(indexables : Indexable(Indexable), reuse = false, &) #

Yields each ordered combination of the elements taken from each of the indexables as `Array`s. Traversal of elements starts from the last `Indexable`. If indexables is empty, yields an empty `Array` exactly once.

`#each_cartesian` is preferred over this class method when the quantity of indexables is known in advance.

    Indexable.each_cartesian([%w[Alice Bob Carol], [1, 2]]) do |name, n|
      puts "#{n}. #{name}"
    end

Prints

    1. Alice
    2. Alice
    1. Bob
    2. Bob
    1. Carol
    2. Carol

By default, a new `Array` is created and yielded for each combination.

- If reuse is an `Array`, it will be reused
- If reuse is truthy, the method will create a new `Array` and reuse it
- If reuse is falsey, no `Array`s will be reused.

This can be used to prevent many memory allocations when each combination of interest is to be used in a read-only fashion.

def self.each_cartesian(indexables : Indexable(Indexable), reuse = false) #

Returns an iterator that enumerates the ordered combinations of elements taken from the indexables as `Array`s. Traversal of elements starts from the last `Indexable`. If indexables is empty, the returned iterator produces one empty `Array`, then stops.

`#each_cartesian` is preferred over this class method when the quantity of indexables is known in advance.

    iter = Indexable.each_cartesian([%w[N S], %w[E W]])
    iter.next # => ["N", "E"]
    iter.next # => ["N", "W"]
    iter.next # => ["S", "E"]
    iter.next # => ["S", "W"]
    iter.next # => Iterator::Stop::INSTANCE

By default, a new `Array` is created and returned for each combination.

- If reuse is an `Array`, it will be reused
- If reuse is truthy, the method will create a new `Array` and reuse it
- If reuse is falsey, no `Array`s will be reused.

This can be used to prevent many memory allocations when each combination of interest is to be used in a read-only fashion.

##
Instance Method Detail

def [](index : Int) #

Returns the element at the given index.

Negative indices can be used to start counting from the end of the array. Raises `IndexError` if trying to access an element outside the array's range.

    ary = ['a', 'b', 'c']
    ary[0]  # => 'a'
    ary[2]  # => 'c'
    ary[-1] # => 'c'
    ary[-2] # => 'b'

    ary[3]  # raises IndexError
    ary[-4] # raises IndexError

def []?(index : Int) #

Returns the element at the given index.

Negative indices can be used to start counting from the end of the array. Returns `nil` if trying to access an element outside the array's range.

    ary = ['a', 'b', 'c']
    ary[0]?  # => 'a'
    ary[2]?  # => 'c'
    ary[-1]? # => 'c'
    ary[-2]? # => 'b'

    ary[3]?  # => nil
    ary[-4]? # => nil

def bsearch(& : T -> _) #

By using binary search, returns the first element for which the passed block returns a truthy value.

If the block returns a falsey value, the element to be found lies behind. If the block returns a truthy value, the element to be found is itself or lies in front.

Binary search needs the collection to be sorted in regards to the search criterion.

Returns `nil` if the block didn't return a truthy value for any element.

    [2, 5, 7, 10].bsearch { |x| x >= 4 } # => 5
    [2, 5, 7, 10].bsearch { |x| x > 10 } # => nil

def bsearch_index(& : T, Int32 -> _) #

By using binary search, returns the index of the first element for which the passed block returns a truthy value.

If the block returns a falsey value, the element to be found lies behind. If the block returns a truthy value, the element to be found is itself or lies in front.

Binary search needs the collection to be sorted in regards to the search criterion.

Returns `nil` if the block didn't return a truthy value for any element.

    [2, 5, 7, 10].bsearch_index { |x, i| x >= 4 } # => 1
    [2, 5, 7, 10].bsearch_index { |x, i| x > 10 } # => nil

def cartesian_product(*others : Indexable) #

Returns an `Array` of all ordered combinations of elements taken from each of `self` and others as `Tuple`s. Traversal of elements starts from the last `Indexable` argument.

    [1, 2, 3].cartesian_product({'a', 'b'})                     # => [{1, 'a'}, {1, 'b'}, {2, 'a'}, {2, 'b'}, {3, 'a'}, {3, 'b'}]
    ['a', 'b'].cartesian_product({1, 2}, {'c', 'd'}).map &.join # => ["a1c", "a1d", "a2c", "a2d", "b1c", "b1d", "b2c", "b2d"]

def combinations(size : Int = self.size) #

Returns an `Array` with all possible combinations of size of `self`.

    a = [1, 2, 3]
    a.combinations    # => [[1, 2, 3]]
    a.combinations(1) # => [[1], [2], [3]]
    a.combinations(2) # => [[1, 2], [1, 3], [2, 3]]
    a.combinations(3) # => [[1, 2, 3]]
    a.combinations(0) # => [[]]
    a.combinations(4) # => []

def dig(index : Int, *subindexes) #

Traverses the depth of a structure and returns the value, otherwise raises `IndexError`.

    ary = [{1, 2, 3, {4, 5, 6}}]
    ary.dig(0, 3, 2) # => 6
    ary.dig(0, 3, 3) # raises IndexError

def dig?(index : Int, *subindexes) #

Traverses the depth of a structure and returns the value. Returns `nil` if not found.

    ary = [{1, 2, 3, {4, 5, 6}}]
    ary.dig?(0, 3, 2) # => 6
    ary.dig?(0, 3, 3) # => nil

def each(& : T -> ) #

Calls the given block once for each element in `self`, passing that element as a parameter.

    a = ["a", "b", "c"]
    a.each { |x| print x, " -- " }

produces:

    a -- b -- c --

def each #

Returns an `Iterator` for the elements of `self`.

    a = ["a", "b", "c"]
    iter = a.each
    iter.next # => "a"
    iter.next # => "b"

The returned iterator keeps a reference to `self`: if the array changes, the returned values of the iterator change as well.

def each(*, start : Int, count : Int, & : T -> ) #

Calls the given block once for `count` number of elements in `self` starting from index `start`, passing each element as a parameter.

Negative indices count backward from the end of the array. (-1 is the last element).

Raises `IndexError` if the starting index is out of range. Raises `ArgumentError` if `count` is a negative number.

    array = ["a", "b", "c", "d", "e"]
    array.each(start: 1, count: 3) { |x| print x, " -- " }

produces:

    b -- c -- d --

def each(*, within range : Range, & : T -> ) #

Calls the given block once for all elements at indices within the given `range`, passing each element as a parameter.

Raises `IndexError` if the starting index is out of range.

    array = ["a", "b", "c", "d", "e"]
    array.each(within: 1..3) { |x| print x, " -- " }

produces:

    b -- c -- d --

def each_cartesian(*others : Indexable, &) #

Yields each ordered combination of the elements taken from each of `self` and others as a `Tuple`. Traversal of elements starts from the last `Indexable` argument.

    ["Alice", "Bob"].each_cartesian({1, 2, 3}) do |name, n|
      puts "#{n}. #{name}"
    end

Prints

    1. Alice
    2. Alice
    3. Alice
    1. Bob
    2. Bob
    3. Bob

def each_cartesian(*others : Indexable) #

Returns an iterator that enumerates the ordered combinations of elements taken from each of `self` and others as `Tuple`s. Traversal of elements starts from the last `Indexable` argument.

    iter = {1, 2, 3}.each_cartesian({'a', 'b'})
    iter.next # => {1, 'a'}
    iter.next # => {1, 'b'}
    iter.next # => {2, 'a'}
    iter.next # => {2, 'b'}
    iter.next # => {3, 'a'}
    iter.next # => {3, 'b'}
    iter.next # => Iterator::Stop::INSTANCE

def each_combination(size : Int = self.size, reuse = false, &) : Nil #

Yields each possible combination of size of `self`.

    a = [1, 2, 3]
    sums = [] of Int32
    a.each_combination(2) { |p| sums << p.sum } # => nil
    sums                                        # => [3, 4, 5]

By default, a new array is created and yielded for each combination. If reuse is given, the array can be reused: if reuse is an `Array`, this array will be reused; if reuse if truthy, the method will create a new array and reuse it. This can be used to prevent many memory allocations when each slice of interest is to be used in a read-only fashion.

def each_combination(size : Int = self.size, reuse = false) #

Returns an `Iterator` over each possible combination of size of `self`.

    iter = [1, 2, 3, 4].each_combination(3)
    iter.next # => [1, 2, 3]
    iter.next # => [1, 2, 4]
    iter.next # => [1, 3, 4]
    iter.next # => [2, 3, 4]
    iter.next # => #<Iterator::Stop>

By default, a new array is created and returned for each combination. If reuse is given, the array can be reused: if reuse is an `Array`, this array will be reused; if reuse if truthy, the method will create a new array and reuse it. This can be used to prevent many memory allocations when each slice of interest is to be used in a read-only fashion.

def each_index(& : Int32 -> ) : Nil #

Calls the given block once for each index in `self`, passing that index as a parameter.

    a = ["a", "b", "c"]
    a.each_index { |x| print x, " -- " }

produces:

    0 -- 1 -- 2 --

def each_index #

Returns an `Iterator` for each index in `self`.

    a = ["a", "b", "c"]
    iter = a.each_index
    iter.next # => 0
    iter.next # => 1

The returned iterator keeps a reference to `self`. If the array changes, the returned values of the iterator will change as well.

def each_index(*, start : Int, count : Int, &) #

Calls the given block once for `count` number of indices in `self` starting from index `start`, passing each index as a parameter.

Negative indices count backward from the end of the array. (-1 is the last element).

Raises `IndexError` if the starting index is out of range. Raises `ArgumentError` if `count` is a negative number.

    array = ["a", "b", "c", "d", "e"]
    array.each_index(start: -3, count: 2) { |x| print x, " -- " }

produces:

    2 -- 3 --

def each_permutation(size : Int = self.size, reuse = false, &) : Nil #

Yields each possible permutation of size of `self`.

    a = [1, 2, 3]
    sums = [] of Int32
    a.each_permutation(2) { |p| sums << p.sum } # => nil
    sums                                        # => [3, 4, 3, 5, 4, 5]

By default, a new array is created and yielded for each permutation. If reuse is given, the array can be reused: if reuse is an `Array`, this array will be reused; if reuse if truthy, the method will create a new array and reuse it. This can be used to prevent many memory allocations when each slice of interest is to be used in a read-only fashion.

def each_permutation(size : Int = self.size, reuse = false) #

Returns an `Iterator` over each possible permutation of size of `self`.

    iter = [1, 2, 3].each_permutation
    iter.next # => [1, 2, 3]
    iter.next # => [1, 3, 2]
    iter.next # => [2, 1, 3]
    iter.next # => [2, 3, 1]
    iter.next # => [3, 1, 2]
    iter.next # => [3, 2, 1]
    iter.next # => #<Iterator::Stop>

By default, a new array is created and returned for each permutation. If reuse is given, the array can be reused: if reuse is an `Array`, this array will be reused; if reuse if truthy, the method will create a new array and reuse it. This can be used to prevent many memory allocations when each slice of interest is to be used in a read-only fashion.

def each_repeated_combination(size : Int = self.size, reuse = false, &) : Nil #

Yields each possible combination with repeated elements of size of `self`.

    a = [1, 2, 3]
    sums = [] of Int32
    a.each_repeated_combination(2) { |p| sums << p.sum } # => nil
    sums                                                 # => [2, 3, 4, 4, 5, 6]

By default, a new array is created and yielded for each combination. If reuse is given, the array can be reused: if reuse is an `Array`, this array will be reused; if reuse if truthy, the method will create a new array and reuse it. This can be used to prevent many memory allocations when each slice of interest is to be used in a read-only fashion.

def each_repeated_combination(size : Int = self.size, reuse = false) #

Returns an `Iterator` over each possible combination with repeated elements of size of `self`.

    iter = [1, 2, 3].each_repeated_combination(2)
    iter.next # => [1, 1]
    iter.next # => [1, 2]
    iter.next # => [1, 3]
    iter.next # => [2, 2]
    iter.next # => [2, 3]
    iter.next # => [3, 3]
    iter.next # => #<Iterator::Stop>

By default, a new array is created and returned for each combination. If reuse is given, the array can be reused: if reuse is an `Array`, this array will be reused; if reuse if truthy, the method will create a new array and reuse it. This can be used to prevent many memory allocations when each slice of interest is to be used in a read-only fashion.

def empty? : Bool #

Returns `true` if `self` is empty, `false` otherwise.

    ([] of Int32).empty? # => true
    ([1]).empty?         # => false

def equals?(other : Indexable, &) : Bool #

Optimized version of `#equals?` used when `other` is also an `Indexable`.

def equals?(other, &) #

Determines if `self` equals other according to a comparison done by the given block.

If `self`'s size is the same as other's size, this method yields elements from `self` and other in tandem: if the block returns true for all of them, this method returns `true`. Otherwise it returns `false`.

    a = [1, 2, 3]
    b = ["a", "ab", "abc"]
    a.equals?(b) { |x, y| x == y.size } # => true
    a.equals?(b) { |x, y| x == y }      # => false

def fetch(index : Int, &) #

Returns the element at the given index, if in bounds, otherwise executes the given block with the index and returns its value.

    a = [:foo, :bar]
    a.fetch(0) { :default_value }    # => :foo
    a.fetch(2) { :default_value }    # => :default_value
    a.fetch(2) { |index| index * 3 } # => 6

def fetch(index, default) #

Returns the value at the index given by index, or when not found the value given by default.

    a = [:foo, :bar]
    a.fetch(0, :default_value) # => :foo
    a.fetch(2, :default_value) # => :default_value

def first(&) #

Returns the first element in the collection, If the collection is empty, calls the block and returns its value.

    ([1, 2, 3]).first { 4 }   # => 1
    ([] of Int32).first { 4 } # => 4

def hash(hasher) #

See `Object#hash(hasher)`

def index(object, offset : Int = 0) #

Returns the index of the first appearance of object in `self` starting from the given offset, or `nil` if object is not in `self`.

    [1, 2, 3, 1, 2, 3].index(2, offset: 2) # => 4

def index(offset : Int = 0, & : T -> ) #

Returns the index of the first object in `self` for which the block is truthy, starting from the given offset, or `nil` if no match is found.

    [1, 2, 3, 1, 2, 3].index(offset: 2) { |x| x < 2 } # => 3

def index!(obj, offset : Int = 0) #

Returns the index of the first appearance of obj in `self` starting from the given offset. Raises `Enumerable::NotFoundError` if obj is not in `self`.

    [1, 2, 3, 1, 2, 3].index!(2, offset: 2) # => 4

def index!(offset : Int = 0, & : T -> ) #

Returns the index of the first object in `self` for which the block is truthy, starting from the given offset. Raises `Enumerable::NotFoundError` if no match is found.

    [1, 2, 3, 1, 2, 3].index!(offset: 2) { |x| x < 2 } # => 3

def join(separator : String | Char | Number = "") : String #

Optimized version of `Enumerable#join` that performs better when all of the elements in this indexable are strings: the total string bytesize to return can be computed before creating the final string, which performs better because there's no need to do reallocations.

def last : T #

Returns the last element of `self` if it's not empty, or raises `IndexError`.

    ([1, 2, 3]).last   # => 3
    ([] of Int32).last # raises IndexError

def last(&) #

Returns the last element of `self` if it's not empty, or the given block's value.

    ([1, 2, 3]).last { 4 }   # => 3
    ([] of Int32).last { 4 } # => 4

def last? : T | Nil #

Returns the last element of `self` if it's not empty, or `nil`.

    ([1, 2, 3]).last?   # => 3
    ([] of Int32).last? # => nil

def permutations(size : Int = self.size) : Array(Array(T)) #

Returns an `Array` with all possible permutations of size of `self`.

    a = [1, 2, 3]
    a.permutations    # => [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
    a.permutations(1) # => [[1],[2],[3]]
    a.permutations(2) # => [[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]]
    a.permutations(3) # => [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
    a.permutations(0) # => [[]]
    a.permutations(4) # => []

def repeated_combinations(size : Int = self.size) : Array(Array(T)) #

Returns an `Array` with all possible combinations with repeated elements of size of `self`.

    a = [1, 2, 3]

    pp a.repeated_combinations
    pp a.repeated_combinations(2)

produces:

    [[1, 1, 1],
     [1, 1, 2],
     [1, 1, 3],
     [1, 2, 2],
     [1, 2, 3],
     [1, 3, 3],
     [2, 2, 2],
     [2, 2, 3],
     [2, 3, 3],
     [3, 3, 3]]
    [[1, 1], [1, 2], [1, 3], [2, 2], [2, 3], [3, 3]]

def reverse_each(& : T -> ) : Nil #

Same as `#each`, but works in reverse.

def reverse_each #

Returns an `Iterator` over the elements of `self` in reverse order.

def rindex(value, offset = size - 1) #

Returns the index of the last appearance of value in `self`, or `nil` if the value is not in `self`.

If offset is given, it defines the position to end the search (elements beyond this point are ignored).

    [1, 2, 3, 2, 3].rindex(2)            # => 3
    [1, 2, 3, 2, 3].rindex(2, offset: 2) # => 1

def rindex(offset = size - 1, & : T -> ) #

Returns the index of the first object in `self` for which the block is truthy, starting from the last object, or `nil` if no match is found.

If offset is given, the search starts from that index towards the first elements in `self`.

    [1, 2, 3, 2, 3].rindex { |x| x < 3 }            # => 3
    [1, 2, 3, 2, 3].rindex(offset: 2) { |x| x < 3 } # => 1

def rindex!(value, offset = size - 1) #

Returns the index of the last appearance of value in `self`, or `nil` if the value is not in `self`.

If offset is given, it defines the position to end the search (elements beyond this point are ignored).

    [1, 2, 3, 2, 3].rindex(2)            # => 3
    [1, 2, 3, 2, 3].rindex(2, offset: 2) # => 1

Raises `Enumerable::NotFoundError` if value is not in `self`.

def rindex!(offset = size - 1, & : T -> ) #

Returns the index of the first object in `self` for which the block is truthy, starting from the last object, or `nil` if no match is found.

If offset is given, the search starts from that index towards the first elements in `self`.

    [1, 2, 3, 2, 3].rindex { |x| x < 3 }            # => 3
    [1, 2, 3, 2, 3].rindex(offset: 2) { |x| x < 3 } # => 1

Raises `Enumerable::NotFoundError` if no match is found.

def sample(n : Int, random : Random = Random::DEFAULT) : Array(T) #

Returns an `Array` of n random elements from `self`, using the given random number generator. All elements have equal probability of being drawn. Sampling is done without replacement; if n is larger than the size of this collection, the returned `Array` has the same size as `self`.

Raises `ArgumentError` if n is negative.

    [1, 2, 3, 4, 5].sample(2)                # => [3, 5]
    {1, 2, 3, 4, 5}.sample(2)                # => [3, 4]
    {1, 2, 3, 4, 5}.sample(2, Random.new(1)) # => [1, 5]

If `self` is not empty and `n` is equal to 1, calls `#sample(random)` exactly once. Thus, random will be left in a different state compared to the implementation in `Enumerable`.

def sample(random : Random = Random::DEFAULT) #

Optimized version of `Enumerable#sample` that runs in O(1) time.

    a = [1, 2, 3]
    a.sample                # => 3
    a.sample                # => 1
    a.sample(Random.new(1)) # => 2

abstract def size #

Returns the number of elements in this container.

def to_a : Array(T) #

Returns an `Array` with all the elements in the collection.

    {1, 2, 3}.to_a # => [1, 2, 3]

def to_a(& : T -> U) : Array(U) forall U #

Returns an `Array` with the results of running block against each element of the collection.

    {1, 2, 3}.to_a { |i| i * 2 } # => [2, 4, 6]

abstract def unsafe_fetch(index : Int) #

Returns the element at the given index, without doing any bounds check.

`Indexable` makes sure to invoke this method with index in `0...size`, so converting negative indices to positive ones is not needed here.

Clients never invoke this method directly. Instead, they access elements with `#[](index)` and `#[]?(index)`.

This method should only be directly invoked if you are absolutely sure the index is in bounds, to avoid a bounds check for a small boost of performance.

def values_at(*indexes : Int) #

Returns a `Tuple` populated with the elements at the given indexes. Raises `IndexError` if any index is invalid.

    ["a", "b", "c", "d"].values_at(0, 2) # => {"a", "c"}