struct

NamedTuple(**T)

Inherits Value / Object

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

See NamedTuple literals in the language reference.

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

Indexing with a symbol or string 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.

Indexing with #[]? does not make the return value nilable if the key is known to exist:

language = {name: "Crystal", year: 2011}
language[:name]?         # => "Crystal"
typeof(language[:name]?) # => String

NamedTuple's own instance classes may also be indexed in a similar manner, returning their value types instead:

tuple = NamedTuple(name: String, year: Int32)
tuple[:name]   # => String
tuple["year"]  # => Int32
tuple[:other]? # => nil

Constructors

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.

Source
new

Creates a named tuple that will contain the given arguments.

With a named tuple literal you cannot create an empty named tuple. This method doesn't have this limitation, which makes it especially useful in macros and generic code.

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

Class methods

[](key : Symbol | String)

Returns the value type for the given key if there is such a key, otherwise raises KeyError. Read the type docs to understand the difference between indexing with a literal or a variable.

alias Foo = NamedTuple(name: String, year: Int32)

Foo[:name]       # => String
Foo["year"]      # => Int32
Foo["year"].zero # => 0
Foo[:other]      # => Error: missing key 'other' for named tuple NamedTuple(name: String, year: Int32).class

key = :year
Foo[key]      # => Int32
Foo[key].zero # Error: undefined method 'zero' for String.class (compile-time type is (Int32.class | String.class))

key = "other"
Foo[key] # raises KeyError
Source
[]?(key : Symbol | String)

Returns the value type for the given key if there is such a key, otherwise returns nil. Read the type docs to understand the difference between indexing with a literal or a variable.

alias Foo = NamedTuple(name: String, year: Int32)

Foo[:name]?          # => String
Foo["year"]?         # => Int32
Foo["year"]?.zero    # => 0
Foo[:other]?         # => nil
typeof(Foo[:other]?) # => Nil

key = :year
Foo[key]?      # => Int32
Foo[key]?.zero # Error: undefined method 'zero' for String.class (compile-time type is (Int32.class | String.class | Nil))

key = "other"
Foo[key]? # => nil
Source
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}
Source

Instance methods

==(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
Source
==(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
Source
[](key : Symbol | String)

Returns the value for the given key if there is such a key, otherwise raises KeyError. Read the type docs to understand the difference between indexing with a literal or a variable.

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

tuple[:name]          # => "Crystal"
typeof(tuple[:name])  # => String
tuple["year"]         # => 2011
typeof(tuple["year"]) # => Int32
tuple[:other]         # Error: missing key 'other' for named tuple NamedTuple(name: String, year: Int32)

key = :name
tuple[key]         # => "Crystal"
typeof(tuple[key]) # => (Int32 | String)

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

key = :other
tuple[key] # raises KeyError
Source
[]?(key : Symbol | String)

Returns the value for the given key if there is such a key, otherwise returns nil. Read the type docs to understand the difference between indexing with a literal or a variable.

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

tuple[:name]?          # => "Crystal"
typeof(tuple[:name]?)  # => String
tuple["year"]?         # => 2011
typeof(tuple["year"]?) # => Int32
tuple[:other]?         # => nil
typeof(tuple[:other]?) # => Nil

key = :name
tuple[key]?         # => "Crystal"
typeof(tuple[key]?) # => (Int32 | String | Nil)

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

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

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

Source
dig(key : Symbol | String, *subkeys)

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

h = {a: {b: {c: [10, 20]}}, x: {a: "b"}}
h.dig :a, :b, :c # => [10, 20]
h.dig "a", "x"   # raises KeyError
Source
dig?(key : Symbol | String, *subkeys)

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

h = {a: {b: {c: [10, 20]}}, x: {a: "b"}}
h.dig? :a, :b, :c # => [10, 20]
h.dig? "a", "x"   # => nil
Source
each

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
Source
each_key

Yields each key in this named tuple.

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

Output:

name
year
Source
each_value

Yields each value in this named tuple.

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

Output:

Crystal
2011
Source
each_with_index(offset = 0, &)

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
Source
empty?

Returns true if this named tuple is empty.

tuple = {name: "Crystal", year: 2011}
tuple.empty? # => false
Source
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
Source
fetch(key : Symbol, &)

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
Source
fetch(key : String, &)

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
Source
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"
Source
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
Source
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
Source
hash(hasher)

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

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

Source
inspect

Same as to_s.

Source
keys

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

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

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"]
Source
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"}
Source
merge

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"}
Source
pretty_print(pp)
Source
reverse_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 are used from self (original tuple)

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

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

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

Returns the number of elements in this named tuple.

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

Returns a Tuple of symbols with the keys in this named tuple, sorted by name.

tuple = {foo: 1, bar: 2, baz: 3}
tuple.sorted_keys # => {:bar, :baz, :foo}
Source
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}]

NOTE: to_a on an empty named tuple produces an Array(Tuple(Symbol, NoReturn))

Source
to_a

Returns an Array with the results of running block against tuples with key and values belonging to this NamedTuple.

tuple = {first_name: "foo", last_name: "bar"}
tuple.to_a(&.last.capitalize) # => ["Foo", "Bar"]

NOTE: to_a on an empty named tuple produces an Array(Tuple(Symbol, NoReturn))

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

NOTE: to_h on an empty named tuple produces a Hash(Symbol, NoReturn)

Source
to_json(json : JSON::Builder)
Source
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})
Source
values

Returns a Tuple with the values in this named tuple.

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