# struct Slice(T)

- Slice(T)
- Struct
- Value
- Object

##
Overview

A `Slice` is a `Pointer` with an associated size.

While a pointer is unsafe because no bound checks are performed when reading from and writing to it, reading from and writing to a slice involve bound checks. In this way, a slice is a safe alternative to `Pointer`.

A Slice can be created as read-only: trying to write to it will raise. For example the slice of bytes returned by `String#to_slice` is read-only.

##
Included Modules

- Comparable(Slice(T))
- Indexable(T)

##
Defined in:

##
Constructors

- .new(ctx : YAML::ParseContext, node : YAML::Nodes::Node)
- .new(pointer : Pointer(T), size : Int, *, read_only = false)

  Creates a slice to the given pointer, bounded by the given size.

- .new(size : Int, value : T, *, read_only = false)

  Allocates `size * sizeof(T)` bytes of heap memory initialized to value and returns a slice pointing to that memory.

- .new(size : Int, *, read_only = false)

  Allocates `size * sizeof(T)` bytes of heap memory initialized to zero and returns a slice pointing to that memory.

- .new(size : Int, *, read_only = false, &)

  Allocates `size * sizeof(T)` bytes of heap memory initialized to the value returned by the block (which is invoked once with each index in the range `0...size`) and returns a slice pointing to that memory.

##
Class Method Summary

- .empty

  Creates an empty slice.

##
Instance Method Summary

- #+(offset : Int)

  Returns a new slice that is offset elements apart from this slice.

- #<=>(other : Slice(U)) forall U

  Combined comparison operator.

- #==(other : Slice(U)) : Bool forall U

  Returns `true` if `self` and other have the same size and all their elements are equal, `false` otherwise.

- #[](range : Range)

  Returns a new slice with the elements in the given range.

- #[](start : Int, count : Int)

  Returns a new slice that starts at start elements from this slice's start, and of count size.

- #[]=(index : Int, value : T)

  Sets the given value at the given index.

- #[]?(start : Int, count : Int)

  Returns a new slice that starts at start elements from this slice's start, and of count size.

- #[]?(range : Range)

  Returns a new slice with the elements in the given range.

- #bytesize
- #clone

  Returns a deep copy of this slice.

- #copy_from(source : Pointer(T), count)
- #copy_from(source : self)

  Copies the contents of source into this slice.

- #copy_to(target : Pointer(T), count)
- #copy_to(target : self)

  Copies the contents of this slice into target.

- #dup

  Returns a shallow copy of this slice.

- #hash(hasher)

  See `Object#hash(hasher)`

- #hexdump

  Returns a hexdump of this slice, assuming it's a `Slice(UInt8)`.

- #hexstring

  Returns a hexstring representation of this slice, assuming it's a `Slice(UInt8)`.

- #inspect(io : IO) : Nil

  Appends this struct's name and instance variables names and values to the given IO.

- #map(*, read_only = false, &block : T -> U) forall U

  Returns a new slice where elements are mapped by the given block.

- #map!(&)

  Invokes the given block for each element of `self`, replacing the element with the value returned by the block.

- #map_with_index(offset = 0, *, read_only = false, &block : T, Int32 -> U) forall U

  Like `#map`, but the block gets passed both the element and its index.

- #map_with_index!(offset = 0, &block : T, Int32 -> T)

  Like `#map!`, but the block gets passed both the element and its index.

- #move_from(source : Pointer(T), count)
- #move_from(source : self)

  Moves the contents of source into this slice.

- #move_to(target : Pointer(T), count)
- #move_to(target : self)

  Moves the contents of this slice into target.

- #pretty_print(pp) : Nil
- #read_only? : Bool

  Returns `true` if this slice cannot be written to.

- #reverse!

  Reverses in-place all the elements of `self`.

- #shuffle!(random = Random::DEFAULT)
- #size : Int32

  Returns the size of this slice.

- #sort : Slice(T)

  Returns a new slice with all elements sorted based on the return value of their comparison method `#<=>`

- #sort(&block : T, T -> U) : Slice(T) forall U

  Returns a new slice with all elements sorted based on the comparator in the given block.

- #sort! : Slice(T)

  Modifies `self` by sorting all elements based on the return value of their comparison method `#<=>`

- #sort!(&block : T, T -> U) : Slice(T) forall U

  Modifies `self` by sorting all elements based on the comparator in the given block.

- #sort_by(&block : T -> _) : Slice(T)

  Returns a new array with all elements sorted.

- #sort_by!(&block : T -> _) : Slice(T)

  Modifies `self` by sorting all elements.

- #to_a

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

- #to_s(io : IO) : Nil

  Same as `#inspect(io)`.

- #to_slice
- #to_unsafe : Pointer(T)

  Returns this slice's pointer.

- #to_yaml(yaml : YAML::Nodes::Builder)
- #unsafe_fetch(index : Int)

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

##
Macro Summary

- [](*args, read_only = false)

  Creates a new `Slice` with the given args.

### Instance methods inherited from module `Comparable(Slice(T))`

<(other : T) <, <=(other : T) <=, <=>(other : T) <=>, ==(other : T) ==, >(other : T) >, >=(other : T) >=, clamp(min, max)
clamp(range : Range) clamp

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

[](index : Int) [], []?(index : Int) []?, bsearch(&block : T -> Bool) bsearch, bsearch_index(&block : T, Int32 -> Bool) bsearch_index, dig(index : Int, *subindexes) dig, dig?(index : Int, *subindexes) dig?, each(*, start : Int, count : Int, &)
each(*, within range : Range, &)
each(&)
each each, each_index(*, start : Int, count : Int, &)
each_index(&) : Nil
each_index each_index, empty? empty?, equals?(other : Indexable, &)
equals?(other, &) equals?, fetch(index, default)
fetch(index : Int, &) fetch, first
first(&) first, first? first?, hash(hasher) hash, index(object, offset : Int = 0)
index(offset : Int = 0, &) index, join(separator = "") join, last
last(&) last, last? last?, reverse_each(&) : Nil
reverse_each reverse_each, rindex(offset = size - 1, &)
rindex(value, offset = size - 1) rindex, sample(random = Random::DEFAULT) sample, size size, to_a to_a, unsafe_fetch(index : Int) unsafe_fetch, values_at(*indexes : Int) values_at

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

all?(&)
all?(pattern)
all? all?, any?(&)
any?(pattern)
any? any?, chunks(&block : T -> U) forall U chunks, compact_map(&) compact_map, count(&)
count(item) count, cycle(n, &)
cycle(&) cycle, each(&block : 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_with_index(offset = 0, &) each_with_index, each_with_object(obj, &) each_with_object, find(if_none = nil, &) find, first(count : Int)
first first, first? first?, flat_map(&block : T -> Array(U) | Iterator(U) | U) forall U flat_map, grep(pattern) grep, group_by(&block : 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, includes?(obj) includes?, index(&)
index(obj) index, index_by(&block : T -> U) forall U index_by, join(separator = "", &)
join(separator, io, &)
join(separator, io)
join(separator = "") join, map(&block : T -> U) forall U map, map_with_index(offset = 0, &block : T, Int32 -> U) forall U map_with_index, max max, max? max?, max_by(&block : T -> U) forall U max_by, max_by?(&block : T -> U) forall U max_by?, max_of(&block : T -> U) forall U max_of, max_of?(&block : T -> U) forall U max_of?, min min, min? min?, min_by(&block : T -> U) forall U min_by, min_by?(&block : T -> U) forall U min_by?, min_of(&block : T -> U) forall U min_of, min_of?(&block : T -> U) forall U min_of?, minmax minmax, minmax? minmax?, minmax_by(&block : T -> U) forall U minmax_by, minmax_by?(&block : T -> U) forall U minmax_by?, minmax_of(&block : T -> U) forall U minmax_of, minmax_of?(&block : T -> U) forall U minmax_of?, none?
none?(pattern)
none?(&) none?, one?(&)
one?(pattern)
one? one?, partition(&) partition, product(&)
product(initial : Number, &)
product
product(initial : Number) product, reduce(memo, &)
reduce(&) reduce, reduce?(&) reduce?, reject(&block : T -> )
reject(type : U.class) forall U
reject(pattern) reject, select(pattern)
select(type : U.class) forall U
select(&block : T -> ) select, size size, skip(count : Int) skip, skip_while(&) skip_while, sum(initial)
sum
sum(initial, &)
sum(&) sum, take_while(&) take_while, tally : Hash(T, Int32) tally, to_a to_a, to_h
to_h(&block : T -> Tuple(K, V)) forall K, V to_h, to_set to_set, zip(*others : Indexable | Iterable | Iterator, &)
zip(*others : Indexable | Iterable | Iterator) zip, zip?(*others : Indexable | Iterable | Iterator, &)
zip?(*others : Indexable | Iterable | Iterator) zip?

### 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_slice(count : Int, reuse = false) each_slice, 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

### Instance methods inherited from struct `Struct`

==(other) : Bool ==, hash(hasher) hash, inspect(io : IO) : Nil inspect, pretty_print(pp) : Nil pretty_print, to_s(io : IO) : Nil to_s

### Instance methods inherited from struct `Value`

==(other : JSON::Any)
==(other : YAML::Any)
==(other) ==, dup dup

### Instance methods inherited from class `Object`

!=(other) !=, !~(other) !~, ==(other) ==, ===(other : JSON::Any)
===(other : YAML::Any)
===(other) ===, =~(other) =~, __crystal_pseudo_! : Bool __crystal_pseudo_!, __crystal_pseudo_as(type : Class) __crystal_pseudo_as, __crystal_pseudo_as?(type : Class) __crystal_pseudo_as?, __crystal_pseudo_is_a?(type : Class) : Bool __crystal_pseudo_is_a?, __crystal_pseudo_nil? : Bool __crystal_pseudo_nil?, __crystal_pseudo_responds_to?(name : Symbol) : Bool __crystal_pseudo_responds_to?, class class, dup dup, hash(hasher)
hash hash, inspect : String
inspect(io : IO) : Nil inspect, itself itself, not_nil! not_nil!, pretty_inspect(width = 79, newline = "\n", indent = 0) : String pretty_inspect, pretty_print(pp : PrettyPrint) : Nil pretty_print, tap(&) tap, to_json(io : IO)
to_json to_json, to_pretty_json(indent : String = " ")
to_pretty_json(io : IO, indent : String = " ") to_pretty_json, to_s : String
to_s(io : IO) : Nil to_s, to_yaml(io : IO)
to_yaml to_yaml, try(&) try, unsafe_as(type : T.class) forall T unsafe_as

### Class methods inherited from class `Object`

from_json(string_or_io, root : String)
from_json(string_or_io) from_json, from_yaml(string_or_io : String | IO) from_yaml

##
Constructor Detail

def self.new(ctx : YAML::ParseContext, node : YAML::Nodes::Node) #
def self.new(pointer : Pointer(T), size : Int, *, read_only = false) #

Creates a slice to the given pointer, bounded by the given size. This method does not allocate heap memory.

    ptr = Pointer.malloc(9) { |i| ('a'.ord + i).to_u8 }

    slice = Slice.new(ptr, 3)
    slice.size # => 3
    slice      # => Bytes[97, 98, 99]

    String.new(slice) # => "abc"

def self.new(size : Int, value : T, *, read_only = false) #

Allocates `size * sizeof(T)` bytes of heap memory initialized to value and returns a slice pointing to that memory.

The memory is allocated by the `GC`, so when there are no pointers to this memory, it will be automatically freed.

    slice = Slice.new(3, 10)
    slice # => Slice[10, 10, 10]

def self.new(size : Int, *, read_only = false) #

Allocates `size * sizeof(T)` bytes of heap memory initialized to zero and returns a slice pointing to that memory.

The memory is allocated by the `GC`, so when there are no pointers to this memory, it will be automatically freed.

Only works for primitive integers and floats (`UInt8`, `Int32`, `Float64`, etc.)

    slice = Slice(UInt8).new(3)
    slice # => Bytes[0, 0, 0]

def self.new(size : Int, *, read_only = false, &) #

Allocates `size * sizeof(T)` bytes of heap memory initialized to the value returned by the block (which is invoked once with each index in the range `0...size`) and returns a slice pointing to that memory.

The memory is allocated by the `GC`, so when there are no pointers to this memory, it will be automatically freed.

    slice = Slice.new(3) { |i| i + 10 }
    slice # => Slice[10, 11, 12]

##
Class Method Detail

def self.empty #

Creates an empty slice.

    slice = Slice(UInt8).empty
    slice.size # => 0

##
Instance Method Detail

def +(offset : Int) #

Returns a new slice that is offset elements apart from this slice.

    slice = Slice.new(5) { |i| i + 10 }
    slice # => Slice[10, 11, 12, 13, 14]

    slice2 = slice + 2
    slice2 # => Slice[12, 13, 14]

def <=>(other : Slice(U)) forall U #

Combined comparison operator.

Returns a negative number, `0`, or a positive number depending on whether `self` is less than other, equals other.

It compares the elements of both slices in the same position using the `#<=>` operator. As soon as one of such comparisons returns a non-zero value, that result is the return value of the comparison.

If all elements are equal, the comparison is based on the size of the arrays.

    Bytes[8] <=> Bytes[1, 2, 3] # => 7
    Bytes[2] <=> Bytes[4, 2, 3] # => -2
    Bytes[1, 2] <=> Bytes[1, 2] # => 0

def ==(other : Slice(U)) : Bool forall U #

Returns `true` if `self` and other have the same size and all their elements are equal, `false` otherwise.

    Bytes[1, 2] == Bytes[1, 2]    # => true
    Bytes[1, 3] == Bytes[1, 2]    # => false
    Bytes[1, 2] == Bytes[1, 2, 3] # => false

def [](range : Range) #

Returns a new slice with the elements in the given range.

Negative indices count backward from the end of the slice (`-1` is the last element). Additionally, an empty slice is returned when the starting index for an element range is at the end of the slice.

Raises `IndexError` if the new slice falls outside this slice.

    slice = Slice.new(5) { |i| i + 10 }
    slice # => Slice[10, 11, 12, 13, 14]

    slice[1..3]  # => Slice[11, 12, 13]
    slice[1..33] # raises IndexError

def [](start : Int, count : Int) #

Returns a new slice that starts at start elements from this slice's start, and of count size.

Raises `IndexError` if the new slice falls outside this slice.

    slice = Slice.new(5) { |i| i + 10 }
    slice # => Slice[10, 11, 12, 13, 14]

    slice[1, 3]  # => Slice[11, 12, 13]
    slice[1, 33] # raises IndexError

def []=(index : Int, value : T) #

Sets the given value at the given index.

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

    slice = Slice.new(5) { |i| i + 10 }
    slice[0] = 20
    slice[-1] = 30
    slice # => Slice[20, 11, 12, 13, 30]

    slice[10] = 1 # raises IndexError

def []?(start : Int, count : Int) #

Returns a new slice that starts at start elements from this slice's start, and of count size.

Returns `nil` if the new slice falls outside this slice.

    slice = Slice.new(5) { |i| i + 10 }
    slice # => Slice[10, 11, 12, 13, 14]

    slice[1, 3]?  # => Slice[11, 12, 13]
    slice[1, 33]? # => nil

def []?(range : Range) #

Returns a new slice with the elements in the given range.

Negative indices count backward from the end of the slice (`-1` is the last element). Additionally, an empty slice is returned when the starting index for an element range is at the end of the slice.

Returns `nil` if the new slice falls outside this slice.

    slice = Slice.new(5) { |i| i + 10 }
    slice # => Slice[10, 11, 12, 13, 14]

    slice[1..3]?  # => Slice[11, 12, 13]
    slice[1..33]? # => nil

def bytesize #
def clone #

Returns a deep copy of this slice.

This method allocates memory for the slice copy and stores the return values from calling `#clone` on each item.

def copy_from(source : Pointer(T), count) #
def copy_from(source : self) #

Copies the contents of source into this slice.

Raises `IndexError` if the desination slice cannot fit the data being transferred.

def copy_to(target : Pointer(T), count) #
def copy_to(target : self) #

Copies the contents of this slice into target.

Raises `IndexError` if the desination slice cannot fit the data being transferred e.g. dest.size < self.size.

    src = Slice['a', 'a', 'a']
    dst = Slice['b', 'b', 'b', 'b', 'b']
    src.copy_to dst
    dst             # => Slice['a', 'a', 'a', 'b', 'b']
    dst.copy_to src # raises IndexError

def dup #

Returns a shallow copy of this slice.

This method allocates memory for the slice copy and duplicates the values.

def hash(hasher) #

See `Object#hash(hasher)`

def hexdump #

Returns a hexdump of this slice, assuming it's a `Slice(UInt8)`. This method is specially useful for debugging binary data and incoming/outgoing data in protocols.

    slice = UInt8.slice(97, 62, 63, 8, 255)
    slice.hexdump # => "00000000  61 3e 3f 08 ff                                    a>?.."

def hexstring #

Returns a hexstring representation of this slice, assuming it's a `Slice(UInt8)`.

    slice = UInt8.slice(97, 62, 63, 8, 255)
    slice.hexstring # => "613e3f08ff"

def inspect(io : IO) : Nil #
Description copied from struct Struct

Appends this struct's name and instance variables names and values to the given IO.

    struct Point
      def initialize(@x : Int32, @y : Int32)
      end
    end

    p1 = Point.new 1, 2
    p1.to_s    # "Point(@x=1, @y=2)"
    p1.inspect # "Point(@x=1, @y=2)"

def map(*, read_only = false, &block : T -> U) forall U #

Returns a new slice where elements are mapped by the given block.

    slice = Slice[1, 2.5, "a"]
    slice.map &.to_s # => Slice["1", "2.5", "a"]

def map!(&) #

Invokes the given block for each element of `self`, replacing the element with the value returned by the block. Returns `self`.

    slice = Slice[1, 2, 3]
    slice.map! { |x| x * x }
    slice # => Slice[1, 4, 9]

def map_with_index(offset = 0, *, read_only = false, &block : T, Int32 -> U) forall U #

Like `#map`, but the block gets passed both the element and its index.

Accepts an optional offset parameter, which tells it to start counting from there.

def map_with_index!(offset = 0, &block : T, Int32 -> T) #

Like `#map!`, but the block gets passed both the element and its index.

Accepts an optional offset parameter, which tells it to start counting from there.

def move_from(source : Pointer(T), count) #
def move_from(source : self) #

Moves the contents of source into this slice. source and `self` may overlap; the copy is always done in a non-destructive manner.

Raises `IndexError` if the desination slice cannot fit the data being transferred.

def move_to(target : Pointer(T), count) #
def move_to(target : self) #

Moves the contents of this slice into target. target and `self` may overlap; the copy is always done in a non-destructive manner.

Raises `IndexError` if the desination slice cannot fit the data being transferred e.g. `dest.size < self.size`.

    src = Slice['a', 'a', 'a']
    dst = Slice['b', 'b', 'b', 'b', 'b']
    src.move_to dst
    dst             # => Slice['a', 'a', 'a', 'b', 'b']
    dst.move_to src # raises IndexError

See also: `Pointer#move_to`.

def pretty_print(pp) : Nil #
def read_only? : Bool #

Returns `true` if this slice cannot be written to.

def reverse! #

Reverses in-place all the elements of `self`.

def shuffle!(random = Random::DEFAULT) #
def size : Int32 #

Returns the size of this slice.

    Slice(UInt8).new(3).size # => 3

def sort : Slice(T) #

Returns a new slice with all elements sorted based on the return value of their comparison method `#<=>`

    a = Slice[3, 1, 2]
    a.sort # => Slice[1, 2, 3]
    a      # => Slice[3, 1, 2]

def sort(&block : T, T -> U) : Slice(T) forall U #

Returns a new slice with all elements sorted based on the comparator in the given block.

The block must implement a comparison between two elements a and b, where `a < b` returns `-1`, `a == b` returns `0`, and `a > b` returns `1`. The comparison operator `#<=>` can be used for this.

    a = Slice[3, 1, 2]
    b = a.sort { |a, b| b <=> a }

    b # => Slice[3, 2, 1]
    a # => Slice[3, 1, 2]

def sort! : Slice(T) #

Modifies `self` by sorting all elements based on the return value of their comparison method `#<=>`

    a = Slice[3, 1, 2]
    a.sort!
    a # => Slice[1, 2, 3]

def sort!(&block : T, T -> U) : Slice(T) forall U #

Modifies `self` by sorting all elements based on the comparator in the given block.

The given block must implement a comparison between two elements a and b, where `a < b` returns `-1`, `a == b` returns `0`, and `a > b` returns `1`. The comparison operator `#<=>` can be used for this.

    a = Slice[3, 1, 2]
    a.sort! { |a, b| b <=> a }
    a # => Slice[3, 2, 1]

def sort_by(&block : T -> _) : Slice(T) #

Returns a new array with all elements sorted. The given block is called for each element, then the comparison method `#<=>` is called on the object returned from the block to determine sort order.

    a = Slice["apple", "pear", "fig"]
    b = a.sort_by { |word| word.size }
    b # => Slice["fig", "pear", "apple"]
    a # => Slice["apple", "pear", "fig"]

def sort_by!(&block : T -> _) : Slice(T) #

Modifies `self` by sorting all elements. The given block is called for each element, then the comparison method `#<=>` is called on the object returned from the block to determine sort order.

    a = Slice["apple", "pear", "fig"]
    a.sort_by! { |word| word.size }
    a # => Slice["fig", "pear", "apple"]

def to_a #
Description copied from module Indexable(T)

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

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

def to_s(io : IO) : Nil #
Description copied from struct Struct

Same as `#inspect(io)`.

def to_slice #
def to_unsafe : Pointer(T) #

Returns this slice's pointer.

    slice = Slice.new(3, 10)
    slice.to_unsafe[0] # => 10

def to_yaml(yaml : YAML::Nodes::Builder) #
def unsafe_fetch(index : Int) #
Description copied from module Indexable(T)

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.

##
Macro Detail

macro [](*args, read_only = false) #

Creates a new `Slice` with the given args. The type of the slice will be the union of the type of the given args.

The slice is allocated on the heap.

    slice = Slice[1, 'a']
    slice[0]    # => 1
    slice[1]    # => 'a'
    slice.class # => Slice(Char | Int32)

If `T` is a `Number` then this is equivalent to `Number.slice` (numbers will be coerced to the type `T`)

See also: `Number.slice`.