struct Tuple(T*)
Overview
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 (Int32)
tuple[1] # => "hello" (String)
tuple[2] # => 'x' (Char)
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 # => {1, "hello", 'x'} (Tuple(Int32, String, Char))
Included Modules
Defined in:
tuple.crjson/to_json.cr
yaml/to_yaml.cr
Class Method Summary
-
.new(*args)
Creates a tuple that will contain the given arguments.
- .new(pull : YAML::PullParser)
- .new(pull : JSON::PullParser)
Instance Method Summary
-
#+(other : Tuple)
Returns a tuple that contains self's elements followed by other's elements.
-
#<=>(other : Tuple)
Implements the comparison operator.
-
#<=>(other : self)
Implements the comparison operator.
-
#==(other : self)
Returns
true
if this tuple has the same size as the other tuple and their elements are equal to each other when compared with#==
. -
#==(other : Tuple)
Returns
true
if this tuple has the same size as the other tuple and their elements are equal to each other when compared with#==
. - #==(other)
-
#===(other : Tuple)
Returns
true
ifself
and other have the same size and case equality holds for the elements inself
and other. -
#===(other : self)
Returns
true
if case equality holds for the elements inself
and other. -
#[](index : Int)
Returns the element at the given index.
-
#[]?(index : Int)
Returns the element at the given index or
nil
if out of bounds. -
#at(index : Int)
Returns the element at the given index or raises IndexError if out of bounds.
-
#at(index : Int, &block)
Returns the element at the given index or the value returned by the block if out of bounds.
-
#clone
Returns a tuple containing cloned elements of this tuple using the
#clone
method. -
#dup
Returns self.
-
#each(&block)
Yields each of the elements in this tuple.
-
#each
Returns an
Iterator
for the elements in this tuple. -
#empty?
Returns true if this tuple is empty.
-
#first
Returns the first element of this tuple.
-
#first?
Returns the first element of this tuple, or nil if this is the empty tuple.
-
#hash
Returns a hash value based on this tuple's length and contents.
-
#inspect
Same as
#to_s
. -
#last
Returns the last element of this tuple.
-
#last?
Returns the last element of this tuple, or nil if this is the empty tuple.
-
#map(&block)
Returns a new tuple where elements are mapped by the given block.
-
#reverse
Returns a new tuple where the elements are in reverse order.
-
#reverse_each
Returns an
Iterator
for the elements in this tuple. -
#reverse_each(&block)
Yields each of the elements in this tuple in reverse order.
-
#size
Returns the number of elements in this tuple.
- #to_json(io)
-
#to_s(io)
Appends a string representation of this tuple to the given
IO
. - #to_yaml(yaml : YAML::Generator)
-
#types
Returns a tuple containing the types of this tuple.
-
#values_at(*indexes : Int)
Returns a tuple populated with the elements at the given indexes.
Instance methods inherited from module Comparable(T)
<(other : T)
<,
<=(other : T)
<=,
<=>(other : T)
<=>,
==(other : T)
==,
>(other : T)
>,
>=(other : T)
>=
Instance methods inherited from module Iterable
cyclecycle(n) cycle, each each, each_cons(count : Int) each_cons, each_slice(count : Int) each_slice, each_with_index(offset = 0) each_with_index, each_with_object(obj) each_with_object
Instance methods inherited from module Enumerable(T)
all?all?(&block) all?, any?
any?(&block) any?, compact_map(&block) compact_map, count(item)
count(&block) count, cycle(&block)
cycle(n, &block) cycle, each(&block : T -> _) each, each_cons(count : Int, &block) each_cons, each_slice(count : Int, &block) each_slice, each_with_index(offset = 0, &block) each_with_index, each_with_object(obj, &block) each_with_object, find(if_none = nil, &block) find, first
first(count : Int) first, first? first?, flat_map(&block : T -> Array(U)) flat_map, grep(pattern) grep, group_by(&block : T -> U) group_by, in_groups_of(size : Int, filled_up_with : U = nil, &block)
in_groups_of(size : Int, filled_up_with : U = nil) in_groups_of, includes?(obj) includes?, index(obj)
index(&block) index, index_by(&block : T -> U) index_by, join(separator = "")
join(separator, io, &block)
join(separator = "", &block)
join(separator, io) join, map(&block : T -> U) map, map_with_index(&block : T, Int32 -> U) map_with_index, max max, max? max?, max_by(&block : T -> U) max_by, max_by?(&block : T -> U) max_by?, max_of(&block : T -> U) max_of, max_of?(&block : T -> U) max_of?, min min, min? min?, min_by(&block : T -> U) min_by, min_by?(&block : T -> U) min_by?, min_of(&block : T -> U) min_of, min_of?(&block : T -> U) min_of?, minmax minmax, minmax? minmax?, minmax_by(&block : T -> U) minmax_by, minmax_by?(&block : T -> U) minmax_by?, minmax_of(&block : T -> U) minmax_of, minmax_of?(&block : T -> U) minmax_of?, none?(&block)
none? none?, one?(&block) one?, partition(&block) partition, product(initial : Number, &block)
product
product(initial : Number)
product(&block) product, reduce(memo, &block)
reduce(&block) reduce, reject(&block : T -> ) reject, select(&block : T -> ) select, size size, skip(count : Int) skip, skip_while(&block) skip_while, sum
sum(initial)
sum(&block)
sum(initial, &block) sum, take_while(&block) take_while, to_a to_a, to_h to_h, to_set to_set
Instance methods inherited from struct Value
==(other)
==
Instance methods inherited from class Object
!=(other)
!=,
!~(other)
!~,
==(other)
==,
===(other)===(other : YAML::Any)
===(other : JSON::Any) ===, =~(other) =~, class class, clone clone, crystal_type_id crystal_type_id, dup dup, hash hash, inspect
inspect(io : IO) inspect, itself itself, not_nil! not_nil!, tap(&block) tap, to_json to_json, to_pretty_json(io : IO)
to_pretty_json to_pretty_json, to_s
to_s(io : IO) to_s, to_yaml(io : IO)
to_yaml to_yaml, try(&block) try
Class methods inherited from class Object
==(other : Class)
==,
===(other)
===,
cast(other) : self
cast,
from_json(string_or_io) : self
from_json,
from_yaml(string : String) : self
from_yaml,
hash
hash,
inspect(io)
inspect,
name : String
name,
to_s(io)
to_s,
|(other : U.class)
|
Class Method Detail
Creates a tuple that will contain the given arguments.
This method is useful in macros and generic code because with it you can creates empty tuples, something that you can't do with a tuple literal.
Tuple.new(1, "hello", 'x') #=> {1, "hello", 'x'}
Tuple.new #=> {}
{} # syntax error
Instance Method Detail
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)
Implements 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
See Object#<=>
.
Implements 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
See Object#<=>
.
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 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 Object#===
Returns true
if case equality holds for the elements in self
and other.
{1, 2} === {1, 2} # => true
{1, 2} === {1, 3} # => false
See 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] # => runtime error: 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[0] # => 1
tuple[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 an Iterator
for the elements in this tuple.
{1, 'a'}.each.cycle.first(3).to_a # => [1, 'a', 1]
Returns true if this tuple is empty.
Tuple.new.empty? # => true
{1, 2}.empty? # => false
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
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"}
Returns a new tuple where the elements are in reverse order.
tuple = {1, 2.5, "a"}
tuple.reverse # => {"a", 2.5, 1}
Returns an Iterator
for the elements in this tuple.
{1, 'a'}.reverse_each.cycle.first(3).to_a # => [1, 'a', 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
Appends a string representation of this tuple to the given IO
.
tuple = {1, "hello"}
tuple.to_s # => "{1, \"hello\"}"
Returns a tuple containing the types of this tuple.
tuple = {1, "hello", 'x'}
tuple.types # => {Int32, String, Char}
Returns a tuple populated with the elements at the given indexes. Raises if any index is invalid.
{"a", "b", "c", "d"}.values_at(0, 2) # => {"a", "c"}