The Crystal Programming Language Forum

Enumerable#reduce with initial value

I’m having a hard time understanding the types given to me by the compiler for this code:

h = ["one", "two", "three"].reduce({} of Int32 => String) do |acc, string|
  acc[string.size] = string
end
    
pp h

It gives the type of acc as (compile-time type is (Hash(Int32, String) | String)). Given the initial value, I’m wondering how I’ve indicated that acc could be String at any time.

For what it’s worth this is a trivialized sample and is not very useful code to begin with :smiley:

The Hash#[]= method returns the assigned value. That cause the return type of the block a string, which is supposed to be the acc for the next iteration.

h = ["one", "two", "three"].reduce({} of Int32 => String) do |acc, string|
  acc[string.size] = string
  acc
end
    
pp h

Ah! Totally, that makes sense. Thanks for the clarification

h = ["one", "two", "three"].each_with_object({} of Int32 => String) do |string, acc|
  acc[string.size] = string
end

h = ["one", "two", "three"].to_h {|v| {v.size, v} }

1 Like

Awesome, knew there had to be a simpler way as well. :slight_smile: