- README

- Top Level Namespace
- Adler32
- ArgumentError
- Array
- Atomic
- Base64
  - Error
- Benchmark
  - BM
    - Job
    - Tms
  - IPS
    - Entry
    - Job
- BigFloat
- BigInt
- BigRational
- BitArray
- Bool
- Box
- Bytes
- Channel
  - Buffered
  - ClosedError
  - ReceiveAction
  - SelectAction
  - SendAction
  - Unbuffered
- Char
  - Reader
- Class
- Colorize
  - Object
  - ObjectExtensions
- Comparable
- Complex
- Concurrent
  - CanceledError
- CRC32
- Crypto
  - Bcrypt
    - Error
    - Password
  - Blowfish
  - Subtle
- CSV
  - Builder
    - Row
  - Error
  - Lexer
  - MalformedCSVError
  - Parser
  - Row
  - Token
    - Kind
- Debug
  - DWARF
    - Abbrev
      - Attribute
    - AT
    - FORM
    - Info
      - Value
    - LineNumbers
      - Register
      - Row
      - Sequence
    - LNE
    - LNS
    - Strings
    - TAG
  - ELF
    - Endianness
    - Error
    - Ident
    - Klass
    - Machine
    - OSABI
    - SectionHeader
      - Flags
      - Type
    - Type
- Deque
- Digest
  - Base
  - MD5
  - SHA1
- Dir
- DivisionByZero
- DL
- ECR
- Enum
- Enumerable
  - EmptyError
- ENV
- Errno
- Exception
- Fiber
- File
  - Stat
- FileUtils
- Flate
  - Error
  - Reader
  - Strategy
  - Writer
- Float
  - Primitive
- Float32
- Float64
- GC
  - Stats
- Gzip
  - Error
  - Header
  - Reader
  - Writer
- Hash
- HTML
- HTTP
  - Client
    - BodyType
    - Response
  - CompressHandler
  - ComputedContentTypeHeader
  - Cookie
  - Cookies
  - ErrorHandler
  - FormData
    - Builder
    - Error
    - FileMetadata
    - Parser
    - Part
  - Handler
    - Proc
  - Headers
  - LogHandler
  - Multipart
    - Builder
    - Error
    - Parser
  - Params
    - Builder
  - Request
  - Server
    - Context
    - RequestProcessor
    - Response
  - StaticFileHandler
    - DirectoryListing
  - WebSocket
  - WebSocketHandler
- Indexable
- IndexError
- INI
- Int
  - Primitive
  - Signed
  - Unsigned
- Int16
- Int32
- Int64
- Int8
- InvalidByteSequenceError
- IO
  - Buffered
  - ByteFormat
    - BigEndian
    - LittleEndian
    - NetworkEndian
    - SystemEndian
  - Delimited
  - EncodingOptions
  - EOFError
  - Error
  - FileDescriptor
  - Hexdump
  - Memory
  - MultiWriter
  - Seek
  - Sized
  - Timeout
- IPSocket
- Iterable
- Iterator
  - IteratorWrapper
  - Stop
- JSON
  - Any
  - Builder
    - ArrayState
    - DocumentEndState
    - DocumentStartState
    - ObjectState
    - StartState
    - State
  - Error
  - Lexer
  - ParseException
  - Parser
  - PullParser
  - Token
  - Type
- KeyError
- Levenshtein
  - Finder
- LLVM
  - ABI
    - AArch64
    - ArgKind
    - ArgType
    - ARM
    - FunctionType
    - X86
    - X86_64
      - RegClass
  - AtomicOrdering
  - AtomicRMWBinOp
  - Attribute
  - AttributeIndex
  - BasicBlock
  - BasicBlockCollection
  - Builder
  - CallConvention
  - CodeGenFileType
  - CodeGenOptLevel
  - CodeModel
  - Context
  - DIBuilder
  - DIFlags
  - DwarfTag
  - DwarfTypeEncoding
  - Function
  - FunctionCollection
  - FunctionPassManager
    - Runner
  - GenericValue
  - GlobalCollection
  - InstructionCollection
  - IntPredicate
  - JITCompiler
  - Linkage
  - MemoryBuffer
  - Module
  - ModuleFlag
  - ModulePassManager
  - ParameterCollection
  - PassManagerBuilder
  - PassRegistry
  - PhiTable
  - RealPredicate
  - RelocMode
  - Target
  - TargetData
  - TargetMachine
  - Type
    - Kind
  - Value
    - Kind
  - ValueMethods
  - VerifierFailureAction
- Logger
  - Formatter
  - Severity
- Markdown
  - HTMLRenderer
  - Parser
    - PrefixHeader
    - UnorderedList
  - Renderer
- Math
- Mutex
- NamedTuple
- Nil
- Number
  - Primitive
- OAuth
  - AccessToken
  - Consumer
  - Error
  - RequestToken
- OAuth2
  - AccessToken
    - Bearer
    - Mac
  - Client
  - Error
  - Session
- Object
- OpenSSL
  - Digest
    - Error
    - UnsupportedError
  - DigestBase
  - Error
  - HMAC
  - MD5
  - SHA1
  - SSL
    - Context
      - Client
      - Server
    - Error
    - ErrorType
    - Modes
    - Options
    - Socket
      - Client
      - Server
    - VerifyMode
    - X509VerifyFlags
- OptionParser
  - Exception
  - InvalidOption
  - MissingOption
- PartialComparable
- Pointer
  - Appender
- PrettyPrint
- Proc
- Process
  - Env
  - Status
  - Stdio
  - Tms
- Random
  - MT19937
- Range
- Readline
  - CompletionProc
  - KeyBindingProc
- Reference
- Reflect
- Regex
  - MatchData
  - Options
- SecureRandom
- Set
- Signal
- Slice
- Socket
  - Address
  - Addrinfo
  - Error
  - Family
  - IPAddress
  - Protocol
  - Server
  - Type
  - UNIXAddress
- Spec
  - Expectations
  - Methods
  - ObjectExtensions
- StaticArray
- String
  - Builder
  - RawConverter
- StringPool
- StringScanner
- Struct
- Symbol
- System
- TCPServer
- TCPSocket
- Tempfile
- Termios
  - AttributeSelection
  - BaudRate
  - ControlMode
  - InputMode
  - LineControl
  - LocalMode
  - OutputMode
- Time
  - DayOfWeek
  - EpochConverter
  - EpochMillisConverter
  - Format
    - Error
  - Kind
  - MonthSpan
  - Span
- Tuple
- TypeCastError
- UDPSocket
- UInt16
- UInt32
- UInt64
- UInt8
- Unicode
  - CaseOptions
- Union
- UNIXServer
- UNIXSocket
- URI
  - Error
- Value
- WeakRef
- XML
  - Attributes
  - AttributeType
  - Builder
  - Error
  - HTMLParserOptions
  - Namespace
  - Node
  - NodeSet
  - ParserOptions
  - Reader
  - SaveOptions
  - Type
  - XPathContext
- YAML
  - Any
  - Builder
  - Error
  - EventKind
  - ParseException
  - Parser
  - PullParser
  - Type
- Zip
  - CompressionMethod
  - Error
  - File
    - Entry
  - FileInfo
  - Reader
    - Entry
  - Writer
    - Entry
- Zlib
  - Error
  - Reader
  - Writer

# struct Tuple(*T)

- Tuple(*T)
- Value
- Object

## 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
    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'}

## Included Modules

- Comparable(Tuple(*T))
- Indexable(Union(*T))

## Defined in:

## Class Method Summary

- .from(array : Array)

  Creates a tuple from the given array, with elements casted to the given types.

- .new(pull : JSON::PullParser)
- .new(pull : YAML::PullParser)
- .new(*args : *T)

  Creates a tuple that will contain the given arguments.

## Instance Method Summary

- #+(other : Tuple)

  Returns a tuple that contains `self`'s elements followed by other's elements.

- #<=>(other : self)

  Implements the comparison operator.

- #<=>(other : Tuple)

  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 : self)

  Returns `true` if case equality holds for the elements in `self` and other.

- #===(other : Tuple)

  Returns `true` if `self` and other have the same size and case equality holds for the elements in `self` 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.

- #each(&block) : Nil

  Yields each of the elements in this tuple.

- #first

  Returns the first element of this tuple.

- #first?

  Returns the first element of this tuple, or `nil` if this is the empty tuple.

- #from(array : Array)

  Expects to be called on a tuple of types, creates a tuple from the given array, with types casted appropriately.

- #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.

- #pretty_print(pp) : Nil
- #reverse

  Returns a new tuple where the elements are in reverse order.

- #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(json : JSON::Builder)
- #to_s(io)

  Appends a string representation of this tuple to the given `IO`.

- #to_yaml(yaml : YAML::Builder)
- #types

  Returns the types of this tuple.

- #unsafe_at(index : Int)

### Instance methods inherited from module `Comparable(Tuple(*T))`

<(other : T) <, <=(other : T) <=, <=>(other : T) <=>, ==(other : T) ==, >(other : T) >, >=(other : T) >=

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

[](index : Int) [], []?(index : Int) []?, at(index : Int, &block)
at(index : Int) at, bsearch(&block) bsearch, bsearch_index(&block) bsearch_index, each(&block)
each each, each_index(&block) : Nil
each_index each_index, empty? empty?, equals?(other : Indexable, &block)
equals?(other, &block) equals?, first(&block)
first first, first? first?, hash hash, index(object, offset : Int = 0)
index(offset : Int = 0, &block) index, last
last(&block) last, last? last?, reverse_each(&block) : Nil
reverse_each reverse_each, rindex(offset = size - 1, &block)
rindex(value, offset = size - 1) rindex, sample(random = Random::DEFAULT) sample, size size, unsafe_at(index : Int) unsafe_at, values_at(*indexes : Int) values_at, zip(other : Indexable, &block)
zip(other : Indexable(U)) forall U zip, zip?(other : Indexable, &block)
zip?(other : Indexable(U)) forall U zip?

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

all?(&block)
all? all?, any?(&block)
any? any?, chunks(&block : Union(T) -> U) forall U chunks, compact_map(&block) compact_map, count(&block)
count(item) count, cycle(n, &block)
cycle(&block) cycle, each(&block : Union(T) -> _) each, each_cons(count : Int, reuse = false, &block) each_cons, each_slice(count : Int, reuse = false, &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(count : Int)
first first, first? first?, flat_map(&block : Union(T) -> Array(U) | Iterator(U) | U) forall U flat_map, grep(pattern) grep, group_by(&block : Union(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, &block) forall U in_groups_of, includes?(obj) includes?, index(&block)
index(obj) index, index_by(&block : Union(T) -> U) forall U index_by, join(separator, io)
join(separator = "")
join(separator, io, &block)
join(separator = "", &block) join, map(&block : Union(T) -> U) forall U map, map_with_index(&block : Union(T), Int32 -> U) forall U map_with_index, max max, max? max?, max_by(&block : Union(T) -> U) forall U max_by, max_by?(&block : Union(T) -> U) forall U max_by?, max_of(&block : Union(T) -> U) forall U max_of, max_of?(&block : Union(T) -> U) forall U max_of?, min min, min? min?, min_by(&block : Union(T) -> U) forall U min_by, min_by?(&block : Union(T) -> U) forall U min_by?, min_of(&block : Union(T) -> U) forall U min_of, min_of?(&block : Union(T) -> U) forall U min_of?, minmax minmax, minmax? minmax?, minmax_by(&block : Union(T) -> U) forall U minmax_by, minmax_by?(&block : Union(T) -> U) forall U minmax_by?, minmax_of(&block : Union(T) -> U) forall U minmax_of, minmax_of?(&block : Union(T) -> U) forall U minmax_of?, none?(&block)
none? none?, one?(&block) one?, partition(&block) partition, product(&block)
product(initial : Number, &block)
product
product(initial : Number) product, reduce(&block)
reduce(memo, &block) reduce, reject(&block : Union(T) -> ) reject, select(&block : Union(T) -> ) select, size size, skip(count : Int) skip, skip_while(&block) skip_while, sum(initial)
sum
sum(initial, &block)
sum(&block) sum, take_while(&block) take_while, to_a to_a, to_h to_h, to_set to_set

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

chunk(reuse = false, &block : Union(T) -> U) forall U chunk, 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

### Instance methods inherited from struct `Value`

==(other) ==, dup dup

### Instance methods inherited from class `Object`

!=(other) !=, !~(other) !~, ==(other) ==, ===(other : JSON::Any)
===(other : YAML::Any)
===(other) ===, =~(other) =~, class class, dup dup, hash hash, inspect(io : IO)
inspect 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(&block) 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
to_s(io : IO) to_s, to_yaml(io : IO)
to_yaml to_yaml, try(&block) try

### Class methods inherited from class `Object`

from_json(string_or_io, root : String) : self
from_json(string_or_io) : self from_json, from_yaml(string_or_io) : self from_yaml

## Class Method Detail

def self.from(array : Array) #

Creates a tuple from the given array, with elements casted to the given types.

    Tuple(String, Int64).from(["world", 2])       # => {"world", 2}
    Tuple(String, Int64).from(["world", 2]).class # => {String, Int64}

See also: `#from`.

def self.new(pull : JSON::PullParser) #
def self.new(pull : YAML::PullParser) #
def self.new(*args : *T) #

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

def +(other : Tuple) #

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)

def <=>(other : self) #

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 also: `Object#<=>`.

def <=>(other : Tuple) #

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 also: `Object#<=>`.

def ==(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 `#==`.

    t1 = {1, "hello"}
    t2 = {1.0, "hello"}
    t3 = {2, "hello"}

    t1 == t2 # => true
    t1 == t3 # => false

def ==(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 `#==`.

    t1 = {1, "hello"}
    t2 = {1.0, "hello"}
    t3 = {2, "hello"}

    t1 == t2 # => true
    t1 == t3 # => false

def ==(other) #
def ===(other : self) #

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#===`.

def ===(other : Tuple) #

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#===`.

def [](index : Int) #

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

def []?(index : Int) #

Returns the element at the given index or `nil` if out of bounds.

    tuple = {1, "hello", 'x'}
    tuple[0]? # => 1
    tuple[3]? # => nil

def at(index : Int) #

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

def at(index : Int, &block) #

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

def clone #

Returns a tuple containing cloned elements of this tuple using the `#clone` method.

def each(&block) : Nil #

Yields each of the elements in this tuple.

    tuple = {1, "hello", 'x'}
    tuple.each do |value|
      puts value
    end

Output:

    1
    "hello"
    'x'

def first #

Returns the first element of this tuple. Doesn't compile if the tuple is empty.

    tuple = {1, 2.5}
    tuple.first # => 1

def first? #

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

def from(array : Array) #

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.

    def speak_about(thing : String, n : Int64)
      "I see #{n} #{thing}s"
    end

    data = JSON.parse(%(["world", 2])).as_a
    speak_about(*{String, Int64}.from(data)) # => "I see 2 worlds"

def hash #

Returns a hash value based on this tuple's length and contents.

See also: `Object#hash`.

def inspect #

Same as `#to_s`.

def last #

Returns the last element of this tuple. Doesn't compile if the tuple is empty.

    tuple = {1, 2.5}
    tuple.last # => 2.5

def last? #

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

def map(&block) #

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"}

def pretty_print(pp) : Nil #
def reverse #

Returns a new tuple where the elements are in reverse order.

    tuple = {1, 2.5, "a"}
    tuple.reverse # => {"a", 2.5, 1}

def reverse_each(&block) #

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

def size #

Returns the number of elements in this tuple.

    {'a', 'b'}.size # => 2

def to_json(json : JSON::Builder) #
def to_s(io) #

Appends a string representation of this tuple to the given `IO`.

    tuple = {1, "hello"}
    tuple.to_s # => "{1, \"hello\"}"

def to_yaml(yaml : YAML::Builder) #
def types #

Returns the types of this tuple.

    tuple = {1, "hello", 'x'}
    tuple.types # => Tuple(Int32, String, Char)

def unsafe_at(index : Int) #