Reduced example that shows a Hash working with a Union:
class Client
property buffs = Hash(String, Int32 | Float32).new
end
p = Client.new
p.buffs["frenzy"] = 0
p.buffs["frenzy"] = 0f32
pp p
This works just as the developer would expect! Great.
However, when you have a nested Hash that has a union, and you need to create and assign them, the compiler won't let you. For example:
Use case:
class Zone
property extra_game_update_hash = Hash(Int64, Hash(String, Int32 | Float32)).new
end
class Client
property in_zone_obj : Zone
def initialize
@in_zone_obj = Zone.new
end
end
p = Client.new
p.in_zone_obj.extra_game_update_hash[5_i64] = {"frenzy" => 0}
pp p
This will give an error:
Error: instance variable '@value' of Hash::Entry(Int64, Hash(String, Float32 | Int32)) must be Hash(String, Float32 | Int32), not Hash(String, Int32)
Thus, basically nullifying the opportunity to create nested Hashes and assign them with Hash literals.
This is expected. {"frenzy" => 0} isn't the same type as Hash(String, Int32 | Float32), thus it fails. You would have to cast the hash as the type you want for it to work. I.e. {"frenzy" => 0} of String => Int32 | Float32
Closing because an answer was given and this was already replied (in other issues) many times before.
You would have to cast the hash as the type you want for it to work. I.e.
{"frenzy" => 0} of String => Int32 | Float32
That's like saying we need to do
p.buffs["frenzy"] = 0 of Int32 | Float32
Which isn't valid code, and there is no need, because we already specified the union :). The value will accept Int32 or Float32. The same should be for when we are creating Hashes! The value should map to the same type we already specified, in this case Hash(String, Int32 | Float32). But why do I even bother replying, you don't listen to me at all. Always saying I'm wrong, etc, etc. I'm not here to put down the language FFS, I'm here to offer suggestions on ways to improve it!
I don't even want to post or engage in discussion anymore, I'd honestly just rather PM bcard on the forums with these suggestions/issues. It's pointless, the animosity you guys have against me is not needed.
0_i32 is a (Int32 | Float32) due to a definition of Union. Any integer or float have a union type because union type "has a room" for storing int32 or float32 value.
Now, {"frenzy" => 0} is not a Hash(String, Int32 | Float32) because Hash is a complex object and Hash(String, Int32) has a different memory layout from Hash(String, Int32 | Float32).
it ain't very dev friendly but it's legit from technical perspective...
Most helpful comment
0_i32 is a (Int32 | Float32) due to a definition of Union. Any integer or float have a union type because union type "has a room" for storing int32 or float32 value.
Now, {"frenzy" => 0} is not a Hash(String, Int32 | Float32) because Hash is a complex object and Hash(String, Int32) has a different memory layout from Hash(String, Int32 | Float32).