struct NamedTuple(**T)

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:

named_tuple.cr
json/to_json.cr
yaml/to_yaml.cr

Constructors

Class Method Summary

Instance Method Summary

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)
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, 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.


[View source]
def self.new(ctx : YAML::ParseContext, node : YAML::Nodes::Node) #

[View source]
def self.new(pull : JSON::PullParser) #

[View source]
def self.new #

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

[View source]

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}

[View source]

Instance Method Detail

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

[View source]
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

[View source]
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

[View source]
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

[View source]
def clone #

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


[View source]
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

[View source]
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

[View source]
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

[View source]
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

[View source]
def empty? #

Returns true if this named tuple is empty.

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

[View source]
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

[View source]
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

[View source]
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

[View source]
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

data = JSON.parse(%({"thing": "world", "n": 2})).as_h
speak_about(**{thing: String, n: Int64}.from(data)) # => "I see 2 worlds"

[View source]
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

[View source]
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

[View source]
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)


[View source]
def inspect #

Same as #to_s.


[View source]
def keys #

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

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

[View source]
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"]

[View source]
def 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"}

[View source]
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"}

[View source]
def pretty_print(pp) #

[View source]
def size #

Returns the number of elements in this named tuple.

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

[View source]
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}]

[View source]
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}

[View source]
def to_json(json : JSON::Builder) #

[View source]
def to_s(io) #

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

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

[View source]
def to_yaml(yaml : YAML::Nodes::Builder) #

[View source]
def values #

Returns a Tuple with the values in this named tuple.

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

[View source]