NamedTuple(**T) -

# struct NamedTuple(**T)

- NamedTuple(**T)
- Value
- Object

## Overview

A named tuple is a fixed-size, immutable, stack-allocated mapping of a fixed set of keys to values.

You can think of a `NamedTuple` as an immutable `Hash` whose keys (which are of type `Symbol`), and the types for each key, are known at compile time.

A named tuple can be created with a named tuple literal:

    language = {name: "Crystal", year: 2011} # NamedTuple(name: String, year: Int32)

    language[:name]  # => "Crystal"
    language[:year]  # => 2011
    language[:other] # compile time error

The compiler knows what types are in each key, so when indexing a named tuple with a symbol literal the compiler will return the value for that key and with the expected type, like in the above snippet. Indexing with a symbol literal for which there's no key will give a compile-time error.

Indexing with a symbol that is only known at runtime will return a value whose type is the union of all the types in the named tuple, and might raise `KeyError`.

## Defined in:

## Constructors

- .from(hash : Hash) : self

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

- .new(ctx : YAML::ParseContext, node : YAML::Nodes::Node)
- .new(pull : JSON::PullParser)
- .new(**options : **T)

  Creates a named tuple that will contain the given arguments.

## Class Method Summary

- .types

  Returns the types of this named tuple type.

## Instance Method Summary

- #==(other : NamedTuple)

  Returns `true` if this tuple has the same keys as other, and values for each key are the same in `self` and other.

- #==(other : self)

  Returns `true` if this tuple has the same keys as other, and values for each key are the same in `self` and other.

- #[](key : Symbol | String)

  Returns the value for the given key, if there's such key, otherwise raises `KeyError`.

- #[]?(key : Symbol | String)

  Returns the value for the given key, if there's such key, otherwise returns `nil`.

- #clone

  Returns a named tuple with the same keys but with cloned values, using the `#clone` method.

- #dig(key : Symbol | String, *subkeys)

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

- #dig?(key : Symbol | String, *subkeys)

  Traverses the depth of a structure and returns the value.

- #each(&block) : Nil

  Yields each key and value in this named tuple.

- #each_key(&block) : Nil

  Yields each key in this named tuple.

- #each_value(&block) : Nil

  Yields each value in this named tuple.

- #each_with_index(offset = 0, &block)

  Yields each key and value, together with an index starting at offset, in this named tuple.

- #empty?

  Returns `true` if this named tuple is empty.

- #fetch(key : Symbol | String, default_value)

  Returns the value for the given key, if there's such key, otherwise returns default_value.

- #fetch(key : Symbol, &block)

  Returns the value for the given key, if there's such key, otherwise the value returned by the block.

- #fetch(key : String, &block)

  Returns the value for the given key, if there's such key, otherwise the value returned by the block.

- #from(hash : Hash)

  Expects to be called on a named tuple whose values are types, creates a tuple from the given hash, with types casted appropriately.

- #has_key?(key : String) : Bool

  Returns `true` if this named tuple has the given key, `false` otherwise.

- #has_key?(key : Symbol) : Bool

  Returns `true` if this named tuple has the given key, `false` otherwise.

- #hash(hasher)

  Returns a hash value based on this name tuple's size, keys and values.

- #inspect : String

  Same as `#to_s`.

- #keys

  Returns a `Tuple` of symbols with the keys in this named tuple.

- #map(&block)

  Returns an `Array` populated with the results of each iteration in the given block, which is given each key and value in this named tuple.

- #merge(**other : **U) forall U

  Merges two named tuples into one, returning a new named tuple.

- #merge(other : NamedTuple)

  Merges two named tuples into one, returning a new named tuple.

- #pretty_print(pp)
- #size

  Returns the number of elements in this named tuple.

- #to_a

  Returns a new `Array` of tuples populated with each key-value pair.

- #to_h

  Returns a `Hash` with the keys and values in this named tuple.

- #to_json(json : JSON::Builder)
- #to_s(io : IO) : Nil

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

- #to_yaml(yaml : YAML::Nodes::Builder)
- #values

  Returns a `Tuple` with the values in this named tuple.

### 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) =~, class class, dup dup, hash(hasher)
hash hash, inspect(io : IO) : Nil
inspect : String 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 : String
to_s(io : IO) : Nil to_s, to_yaml(io : IO)
to_yaml to_yaml, try(&block) try, unsafe_as(type : T.class) forall T unsafe_as

### Constructor 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 : String | IO) : self from_yaml

## Constructor Detail

def self.from(hash : Hash) : self #

Creates a named tuple from the given hash, with elements casted to the given types. Here the Int32 | String union is cast to Int32.

    num_or_str = 42.as(Int32 | String)
    NamedTuple(name: String, val: Int32).from({"name" => "number", "val" => num_or_str}) # => {name: "number", val: 42}

    num_or_str = "a string".as(Int32 | String)
    NamedTuple(name: String, val: Int32).from({"name" => "number", "val" => num_or_str}) # raises TypeCastError (cast from String to Int32 failed)

See also: `#from`.

def self.new(ctx : YAML::ParseContext, node : YAML::Nodes::Node) #
def self.new(pull : JSON::PullParser) #
def self.new(**options : **T) #

Creates a named tuple that will contain the given arguments.

This method is useful in macros and generic code because with it you can creates empty named tuples, something that you can't do with a tuple literal.

    NamedTuple.new(name: "Crystal", year: 2011) #=> {name: "Crystal", year: 2011}
    NamedTuple.new # => {}
    {}             # syntax error

## Class Method Detail

def self.types #

Returns the types of this named tuple type.

    tuple = {a: 1, b: "hello", c: 'x'}
    tuple.class.types # => {a: Int32, b: String, c: Char}

## Instance Method Detail

def ==(other : NamedTuple) #

Returns `true` if this tuple has the same keys as other, and values for each key are the same in `self` and other.

    tuple1 = {name: "Crystal", year: 2011}
    tuple2 = {year: 2011, name: "Crystal"}
    tuple3 = {name: "Crystal", year: 2012}
    tuple4 = {name: "Crystal", year: 2011.0}

    tuple1 == tuple2 # => true
    tuple1 == tuple3 # => false
    tuple1 == tuple4 # => true

def ==(other : self) #

Returns `true` if this tuple has the same keys as other, and values for each key are the same in `self` and other.

    tuple1 = {name: "Crystal", year: 2011}
    tuple2 = {year: 2011, name: "Crystal"}
    tuple3 = {name: "Crystal", year: 2012}
    tuple4 = {name: "Crystal", year: 2011.0}

    tuple1 == tuple2 # => true
    tuple1 == tuple3 # => false
    tuple1 == tuple4 # => true

def [](key : Symbol | String) #

Returns the value for the given key, if there's such key, otherwise raises `KeyError`.

    tuple = {name: "Crystal", year: 2011}

    key = :name
    tuple[key] # => "Crystal"

    key = "year"
    tuple[key] # => 2011

    key = :other
    tuple[key] # raises KeyError

def []?(key : Symbol | String) #

Returns the value for the given key, if there's such key, otherwise returns `nil`.

    tuple = {name: "Crystal", year: 2011}

    key = :name
    tuple[key]? # => "Crystal"

    key = "year"
    tuple[key] # => 2011

    key = :other
    tuple[key]? # => nil

def clone #

Returns a named tuple with the same keys but with cloned values, using the `#clone` method.

def dig(key : Symbol | String, *subkeys) #

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

    h = {a: {b: [10, 20, 30]}}
    h.dig "a", "b"                # => [10, 20, 30]
    h.dig "a", "b", "c", "d", "e" # raises KeyError

def dig?(key : Symbol | String, *subkeys) #

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

    h = {a: {b: [10, 20, 30]}}
    h.dig? "a", "b"                # => [10, 20, 30]
    h.dig? "a", "b", "c", "d", "e" # => nil

def each(&block) : Nil #

Yields each key and value in this named tuple.

    tuple = {name: "Crystal", year: 2011}
    tuple.each do |key, value|
      puts "#{key} = #{value}"
    end

Output:

    name = Crystal
    year = 2011

def each_key(&block) : Nil #

Yields each key in this named tuple.

    tuple = {name: "Crystal", year: 2011}
    tuple.each_key do |key|
      puts key
    end

Output:

    name
    year

def each_value(&block) : Nil #

Yields each value in this named tuple.

    tuple = {name: "Crystal", year: 2011}
    tuple.each_value do |value|
      puts value
    end

Output:

    Crystal
    2011

def each_with_index(offset = 0, &block) #

Yields each key and value, together with an index starting at offset, in this named tuple.

    tuple = {name: "Crystal", year: 2011}
    tuple.each_with_index do |key, value, i|
      puts "#{i + 1}) #{key} = #{value}"
    end

Output:

    1) name = Crystal
    2) year = 2011

def empty? #

Returns `true` if this named tuple is empty.

    tuple = {name: "Crystal", year: 2011}
    tuple.empty? # => false

def fetch(key : Symbol | String, default_value) #

Returns the value for the given key, if there's such key, otherwise returns default_value.

    tuple = {name: "Crystal", year: 2011}
    tuple.fetch(:name, "Unknown") # => "Crystal"
    tuple.fetch("year", 0)        # => 2011
    tuple.fetch(:other, 0)        # => 0

def fetch(key : Symbol, &block) #

Returns the value for the given key, if there's such key, otherwise the value returned by the block.

    tuple = {name: "Crystal", year: 2011}
    tuple.fetch(:name) { "Unknown" } # => "Crystal"
    tuple.fetch(:other) { 0 }        # => 0

def fetch(key : String, &block) #

Returns the value for the given key, if there's such key, otherwise the value returned by the block.

    tuple = {name: "Crystal", year: 2011}
    tuple.fetch("name") { "Unknown" } # => "Crystal"
    tuple.fetch("other") { 0 }        # => 0

def from(hash : Hash) #

Expects to be called on a named tuple whose values are types, creates a tuple from the given hash, with types casted appropriately. The hash keys must be either symbols or strings.

This allows you to easily pass a hash as individual named arguments to a method.

    require "json"

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

    hash = JSON.parse(%({"thing": "world", "n": 2})).as_h # hash : Hash(String, JSON::Any)
    hash = hash.transform_values(&.raw)                   # hash : Hash(String, JSON::Any::Type)

    speak_about(**{thing: String, n: Int64}.from(hash)) # => "I see 2 worlds"

def has_key?(key : String) : Bool #

Returns `true` if this named tuple has the given key, `false` otherwise.

    tuple = {name: "Crystal", year: 2011}
    tuple.has_key?(:name)  # => true
    tuple.has_key?(:other) # => false

def has_key?(key : Symbol) : Bool #

Returns `true` if this named tuple has the given key, `false` otherwise.

    tuple = {name: "Crystal", year: 2011}
    tuple.has_key?(:name)  # => true
    tuple.has_key?(:other) # => false

def hash(hasher) #

Returns a hash value based on this name tuple's size, keys and values.

See also: `Object#hash`. See `Object#hash(hasher)`

def inspect : String #

Same as `#to_s`.

def keys #

Returns a `Tuple` of symbols with the keys in this named tuple.

    tuple = {name: "Crystal", year: 2011}
    tuple.keys # => {:name, :year}

def map(&block) #

Returns an `Array` populated with the results of each iteration in the given block, which is given each key and value in this named tuple.

    tuple = {name: "Crystal", year: 2011}
    tuple.map { |k, v| "#{k}: #{v}" } # => ["name: Crystal", "year: 2011"]

def merge(**other : **U) forall U #

Merges two named tuples into one, returning a new named tuple. If a key is defined in both tuples, the value and its type is used from other.

    a = {foo: "Hello", bar: "Old"}
    b = {bar: "New", baz: "Bye"}
    a.merge(b) # => {foo: "Hello", bar: "New", baz: "Bye"}

def merge(other : NamedTuple) #

Merges two named tuples into one, returning a new named tuple. If a key is defined in both tuples, the value and its type is used from other.

    a = {foo: "Hello", bar: "Old"}
    b = {bar: "New", baz: "Bye"}
    a.merge(b) # => {foo: "Hello", bar: "New", baz: "Bye"}

def pretty_print(pp) #
def size #

Returns the number of elements in this named tuple.

    tuple = {name: "Crystal", year: 2011}
    tuple.size # => 2

def to_a #

Returns a new `Array` of tuples populated with each key-value pair.

    tuple = {name: "Crystal", year: 2011}
    tuple.to_a # => [{:name, "Crystal"}, {:year, 2011}]

def to_h #

Returns a `Hash` with the keys and values in this named tuple.

    tuple = {name: "Crystal", year: 2011}
    tuple.to_h # => {:name => "Crystal", :year => 2011}

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

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

    tuple = {name: "Crystal", year: 2011}
    tuple.to_s # => %({name: "Crystal", year: 2011})

def to_yaml(yaml : YAML::Nodes::Builder) #
def values #

Returns a `Tuple` with the values in this named tuple.

    tuple = {name: "Crystal", year: 2011}
    tuple.values # => {"Crystal", 2011}