Is there some function or syntax construction to make next examples work?
Invoke Hash#values_at
function with an Array
argument:
h = {"a" => 1, "b" => 2, "c" => 3}
ary = ["a", "b"]
h.values_at(*ary) # Error: argument to splat must be a tuple, not Array(String)
Pass Hash
to initialize class or struct:
struct Point
def initialize(@x : Int32, @y : Int32)
end
end
h = {"x" => 1, "y" => 2}
Point.new(**h) # Error: argument to double splat must be a named tuple, not Hash(String, Int32)
The first example might be impossible, depending on the circumstances. However if the length of elements is fixed, you can do:
h = {"a" => 1, "b" => 2, "c" => 3}
ary = ["a", "b"]
p h.values_at(*{String, String}.from(ary))
https://carc.in/#/r/3oot See Tuple.from
NamedTuple
supports the same approach:
struct Point
def initialize(@x : Int32, @y : Int32)
end
end
h = {"x" => 1, "y" => 2}
p Point.new(**{x: Int32, y: Int32}.from(h))
https://carc.in/#/r/3oov See NamedTuple.from
Both of these are just some sugar around ensuring types and decomposing the structure manually at runtime and mainly useful when your data comes from an external source, such as being parsed from JSON.
Of course it's preferred to create and use Tuple
over Array
and NamedTuple
over Hash
in the first place where possible.