A tuple is a fixed-size, immutable, stack-allocated sequence of values of possibly different types.
You can think of a Tuple
as an immutable Array
whose types for each position are known at compile time.
A tuple can be created with the usual .new
method or with a tuple literal:
tuple = {1, "hello", 'x'} # Tuple(Int32, String, Char) tuple[0] # => 1 tuple[1] # => "hello" tuple[2] # => 'x'
The compiler knows what types are in each position, so when indexing a tuple with an integer literal the compiler will return the value in that index and with the expected type, like in the above snippet. Indexing with an integer literal outside the bounds of the tuple will give a compile-time error.
Indexing with an integer value that is only known at runtime will return a value whose type is the union of all the types in the tuple, and might raise IndexError
.
Tuples are the preferred way to return fixed-size multiple return values because no memory is needed to be allocated for them:
def one_and_hello {1, "hello"} end one, hello = one_and_hello one # => 1 hello # => "hello"
Good examples of the above are Number#divmod
and Enumerable#minmax
.
Tuples can be splat with the *
operator and passed to methods:
def multiply(string, value) string * value end tuple = {"hey", 2} value = multiply(*tuple) # same as multiply tuple[0], tuple[1] value # => "heyhey"
Finally, when using a splat argument in a method definition its type will be a tuple of the call arguments:
def splat_test(*args) args end tuple = splat_test 1, "hello", 'x' tuple.class # => Tuple(Int32, String, Char) tuple # => {1, "hello", 'x'}
Creates a tuple from the given array, with elements casted to the given types.
Creates a tuple that will contain the given values.
Returns the types of this tuple type.
Returns a tuple that contains self
's elements followed by other's elements.
The comparison operator.
The comparison operator.
Returns true
if this tuple has the same size as the other tuple and their elements are equal to each other when compared with #==
.
Returns true
if this tuple has the same size as the other tuple and their elements are equal to each other when compared with #==
.
Returns false
.
Returns true
if case equality holds for the elements in self
and other.
Returns true
if self
and other have the same size and case equality holds for the elements in self
and other.
Returns the element at the given index.
Returns the element at the given index or nil
if out of bounds.
Returns the element at the given index or raises IndexError if out of bounds.
Returns the element at the given index or the value returned by the block if out of bounds.
Returns a tuple containing cloned elements of this tuple using the #clone
method.
Yields each of the elements in this tuple.
Returns the first element of this tuple.
Returns the first element of this tuple, or nil
if this is the empty tuple.
Expects to be called on a tuple of types, creates a tuple from the given array, with types casted appropriately.
Same as #to_s
.
Returns the last element of this tuple.
Returns the last element of this tuple, or nil
if this is the empty tuple.
Returns a new tuple where elements are mapped by the given block.
Like #map
, but the block gets passed both the element and its index.
Returns a new tuple where the elements are in reverse order.
Yields each of the elements in this tuple in reverse order.
Returns the number of elements in this tuple.
Returns an Array
with all the elements in the collection.
Appends a string representation of this tuple to the given IO
.
Returns the element at the given index, without doing any bounds check.
Comparable(Tuple(*T))
Indexable(Union(*T))
Enumerable(Union(*T))
Iterable(Union(*T))
Value
Object
Object
Creates a tuple from the given array, with elements casted to the given types.
Tuple(String, Int64).from(["world", 2_i64]) # => {"world", 2_i64} Tuple(String, Int64).from(["world", 2_i64]).class # => Tuple(String, Int64)
See also: #from
.
Creates a tuple that will contain the given values.
This method is useful in macros and generic code because with it you can create empty tuples, something that you can't do with a tuple literal.
Tuple.new(1, "hello", 'x') #=> {1, "hello", 'x'} Tuple.new #=> {} {} # syntax error
Returns the types of this tuple type.
tuple = {1, "hello", 'x'} tuple.class.types # => {Int32, String, Char}
Returns a tuple that contains self
's elements followed by other's elements.
t1 = {1, 2} t2 = {"foo", "bar"} t3 = t1 + t2 t3 # => {1, 2, "foo", "bar"} typeof(t3) # => Tuple(Int32, Int32, String, String)
The comparison operator.
Each object in each tuple is compared using the #<=>
operator.
Tuples are compared in an "element-wise" manner; the first element of this tuple is compared with the first one of other using the #<=>
operator, then each of the second elements, etc. As soon as the result of any such comparison is non-zero (i.e. the two corresponding elements are not equal), that result is returned for the whole tuple comparison.
If all the elements are equal, then the result is based on a comparison of the tuple sizes. Thus, two tuples are "equal" according to #<=>
if, and only if, they have the same size and the value of each element is equal to the value of the corresponding element in the other tuple.
{"a", "a", "c"} <=> {"a", "b", "c"} # => -1 {1, 2, 3, 4, 5, 6} <=> {1, 2} # => 1 {1, 2} <=> {1, 2.0} # => 0
The comparison operator.
Each object in each tuple is compared using the #<=>
operator.
Tuples are compared in an "element-wise" manner; the first element of this tuple is compared with the first one of other using the #<=>
operator, then each of the second elements, etc. As soon as the result of any such comparison is non-zero (i.e. the two corresponding elements are not equal), that result is returned for the whole tuple comparison.
If all the elements are equal, then the result is based on a comparison of the tuple sizes. Thus, two tuples are "equal" according to #<=>
if, and only if, they have the same size and the value of each element is equal to the value of the corresponding element in the other tuple.
{"a", "a", "c"} <=> {"a", "b", "c"} # => -1 {1, 2, 3, 4, 5, 6} <=> {1, 2} # => 1 {1, 2} <=> {1, 2.0} # => 0
Returns true
if this tuple has the same size as the other tuple and their elements are equal to each other when compared with #==
.
t1 = {1, "hello"} t2 = {1.0, "hello"} t3 = {2, "hello"} t1 == t2 # => true t1 == t3 # => false
Returns true
if this tuple has the same size as the other tuple and their elements are equal to each other when compared with #==
.
t1 = {1, "hello"} t2 = {1.0, "hello"} t3 = {2, "hello"} t1 == t2 # => true t1 == t3 # => false
Returns true
if case equality holds for the elements in self
and other.
{1, 2} === {1, 2} # => true {1, 2} === {1, 3} # => false
See also: Object#===
.
Returns true
if self
and other have the same size and case equality holds for the elements in self
and other.
{1, 2} === {1, 2, 3} # => false {/o+/, "bar"} === {"foo", "bar"} # => true
See also: Object#===
.
Returns the element at the given index. Read the type docs to understand the difference between indexing with a number literal or a variable.
tuple = {1, "hello", 'x'} tuple[0] # => 1 (Int32) tuple[3] # compile error: index out of bounds for tuple {Int32, String, Char} i = 0 tuple[i] # => 1 (Int32 | String | Char) i = 3 tuple[i] # raises IndexError
Returns the element at the given index or nil
if out of bounds.
tuple = {1, "hello", 'x'} tuple[0]? # => 1 tuple[3]? # => nil
Returns the element at the given index or raises IndexError if out of bounds.
tuple = {1, "hello", 'x'} tuple.at(0) # => 1 tuple.at(3) # raises IndexError
Returns the element at the given index or the value returned by the block if out of bounds.
tuple = {1, "hello", 'x'} tuple.at(0) { 10 } # => 1 tuple.at(3) { 10 } # => 10
Yields each of the elements in this tuple.
tuple = {1, "hello", 'x'} tuple.each do |value| puts value end
Output:
1 "hello" 'x'
Returns the first element of this tuple. Doesn't compile if the tuple is empty.
tuple = {1, 2.5} tuple.first # => 1
Returns the first element of this tuple, or nil
if this is the empty tuple.
tuple = {1, 2.5} tuple.first? # => 1 empty = Tuple.new empty.first? # => nil
Expects to be called on a tuple of types, creates a tuple from the given array, with types casted appropriately.
This allows you to easily pass an array as individual arguments to a method.
require "json" def speak_about(thing : String, n : Int64) "I see #{n} #{thing}s" end data = JSON.parse(%(["world", 2])).as_a.map(&.raw) speak_about(*{String, Int64}.from(data)) # => "I see 2 worlds"
Returns the last element of this tuple. Doesn't compile if the tuple is empty.
tuple = {1, 2.5} tuple.last # => 2.5
Returns the last element of this tuple, or nil
if this is the empty tuple.
tuple = {1, 2.5} tuple.last? # => 2.5 empty = Tuple.new empty.last? # => nil
Returns a new tuple where elements are mapped by the given block.
tuple = {1, 2.5, "a"} tuple.map &.to_s # => {"1", "2.5", "a"}
Like #map
, but the block gets passed both the element and its index.
tuple = {1, 2.5, "a"} tuple.map_with_index { |e, i| "tuple[#{i}]: #{e}" } # => {"tuple[0]: 1", "tuple[1]: 2.5", "tuple[2]: a"}
Accepts an optional offset parameter, which tells it to start counting from there.
Returns a new tuple where the elements are in reverse order.
tuple = {1, 2.5, "a"} tuple.reverse # => {"a", 2.5, 1}
Yields each of the elements in this tuple in reverse order.
tuple = {1, "hello", 'x'} tuple.reverse_each do |value| puts value end
Output:
'x' "hello" 1
Returns the number of elements in this tuple.
{'a', 'b'}.size # => 2
Returns an Array
with all the elements in the collection.
{1, 2, 3}.to_a # => [1, 2, 3]
Appends a string representation of this tuple to the given IO
.
tuple = {1, "hello"} tuple.to_s # => "{1, \"hello\"}"
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.
© 2012–2020 Manas Technology Solutions.
Licensed under the Apache License, Version 2.0.
https://crystal-lang.org/api/0.35.1/Tuple.html