https://crystal-lang.org/reference/syntax_and_semantics/union_types.html
The type of a variable or expression can consist of multiple types.
However,
class Client
property buffs : Hash(String, Float32 | Int32)
def initialize
@buffs = {"frenzy" => 0}
end
end
p = Client.new
pp p
Error: instance variable ‘@buffs’ of Client must be Hash(String, Float32 | Int32), not Hash(String, Int32)
class Client
property buffs = Hash(String, Int32 | Float32).new
def initialize
@buffs = {"frenzy" => 0}
end
end
p = Client.new
Hmm, this works.
What’s the difference between
property buffs = Hash(String, Int32 | Float32).new
and
property buffs : Hash(String, Int32 | Float32)
?
Hmm… how come the code above works, but this doesn’t?
class Zone
property extra_game_update_hash = Hash(Int64, Hash(String, Int32 | Float32)).new
end
class Client
property zone_obj : Zone
def initialize
@zone_obj = Zone.new
end
end
p = Client.new
p.zone_obj.extra_game_update_hash[5_i64] = {"frenzy" => 0}
Error:
Error: instance variable ‘@value’ of Hash::Entry(Int64, Hash(String, Float32 | Int32)) must be Hash(String, Float32 | Int32), not Hash(String, Int32)
edit: I changed the title to “nested Hashes”. As I think the bug is only when unions are inside a nested Hash? Not entirely sure.
Check Carcin , the buffs
in this example is a union itself.
In the previous snippent, the : Hash(String, Int32 | Float32)
restrict the type so no union is made.
Aww, I understand now.
What about
property extra_game_update_hash = Hash(Int64, Hash(String, Int32 | Float32)).new
Not using :
, but the compiler still errors out, is that intended?
The type of this expression {"frenzy" => 0}
is Hash(String, Int32)
. These two types:
Hash(String, Int32)
Hash(String, Int32 | Float32)
are not related in any way, these are two different types, no ifs and buts about it.
Look at it this way: you have a generic type Hash(K, V)
, so when you create a concrete type Hash(k1, v1)
, it’s not going to be compatible with another Hash(k2, v2)
, unless k1 == k2
, and v1 == v2
.
In your case, k1
is String
and k2
is also String
, however v1
is Int32 | Float32
, but v2
is Int32
.
Int32 | Float32
and Int32
are two different types. They are not unrelated if used directly, but as soon as you have them inside another type, they lose their relationship and become just two different types.
Hope that helps.
1 Like