Working with hash tables in Crystal is not always ‘crystal’ clear to me
So, given the following type:
alias Params = String | Int32 | Hash(Symbol, Params)
I want to define and populate a hash table with, for example, the following literal data:
foo = {
:bar1 => {:type => "I", :minval => 3, :maxval => 33},
:bar2 => {:type => "I", :minval => 4, :maxval => 44},
:bar3 => {}
}
Applying the advice given by @Blacksmoke16 in a previous post, I end up with the following code:
foo = {} of Symbol => Params
foo[:bar1] = {} of Symbol => Params
foo[:bar2] = {} of Symbol => Params
foo[:bar3] = {} of Symbol => Params
foo[:bar1].as(Hash(Symbol, Params))[:type] = "I"
foo[:bar1].as(Hash(Symbol, Params))[:minval] = 3
foo[:bar1].as(Hash(Symbol, Params))[:maxval] = 33
foo[:bar2].as(Hash(Symbol, Params))[:type] = "I"
foo[:bar2].as(Hash(Symbol, Params))[:minval] = 4
foo[:bar2].as(Hash(Symbol, Params))[:maxval] = 44
p! foo
p! typeof(foo)
p! typeof(foo[:bar1])
p! typeof(foo[:bar1].as(Hash(Symbol, Params))[:maxval])
and the result is what I expect.
foo # => {:bar1 => {:type => "I", :minval => 3, :maxval => 33}, :bar2 => {:type => "I", :minval => 4, :maxval => 44}, :bar3 => {}
typeof(foo) # => Hash(Symbol, Params)
typeof(foo[:bar1]) # => (Hash(Symbol, Params) | Int32 | String)
typeof((foo[:bar1].as(Hash(Symbol, Params)))[:maxval]) # => (Hash(Symbol, Params) | Int32 | String)
But the syntax is a bit heavy, I think. So I try a more compact version:
foo = {
:bar1 => {:type => "I".as(Params), :minval => 3.as(Params)}.as(Params),
# :bar2 => {:type => "I".as(Params), :minval => 4.as(Params), :maxval => 44.as(Params)}.as(Params),
}
p! foo
p! typeof(foo)
p! typeof(foo[:bar1])
This looks ok:
foo # => {:bar1 => {:type => "I", :minval => 3}}
typeof(foo) # => Hash(Symbol, Params)
typeof(foo[:bar1]) # => (Hash(Symbol, Params) | Int32 | String)
but, if I uncomment the second line (:bar2 …), I get the following compilation error:
Error: can't cast Hash(Symbol, Hash(Symbol, Params) | Int32 | String) to Params
Why is adding a 3rd key a problem? I read somewhere that recursive aliases are a bit buggy: is this the explanation of this error?