3

Looking at @mu is too short's answer to another question, I tried a variation:

def anagrams(list)
  h = Hash.new{ [] }
  list.each_with_object(h){ |el, h| h[el.downcase.chars.sort] <<= el }
end

anagrams(['cars', 'for', 'potatoes', 'racs', 'four','scar', 'creams', 'scream'])

(Blindly assuming there would be a<<= operator.) It works, but Hash.new{[]} is not idiomatic at all - I have not found any examples. Is there something wrong with it?

Community
  • 1
  • 1
steenslag
  • 79,051
  • 16
  • 138
  • 171

2 Answers2

3

The reason such code isn't commonly used is that it doesn't insert its return value in the hash, so the user needs to call Hash#[]= to insert the object into the hash (which is what you're doing here: hash[key] <<= val is just short for hash[key] = hash[key] << val)

Mon ouïe
  • 948
  • 5
  • 6
0

It's weird, because it doesn't make any use of what the block ctor provides, but the purpose of the block ctor is to return the default value--if you choose not to do anything with the |h, k|, that's your call.

Dave Newton
  • 158,873
  • 26
  • 254
  • 302
  • 2
    Actually ignoring the arguments results in the surprising behaviour that a value will be returned if a key is missing, but it's not *saved* in the hash! So `h[:foo]` will return an empty list and `h[:foo] << 1` will not give an error, but the result will be immediately discarded and `h[:foo]` will result in `[]` again the next time. – Niklas B. Mar 03 '12 at 21:05
  • @NiklasB. The docs explicitly state that it won't be saved in the hash unless the block does so (at least on apidock.com). – Dave Newton Mar 03 '12 at 21:08
  • 1
    Yeah, and that's the reason why it's not a good idea to use `Hash.new { [] }`. It seems to do something different from what it actually does. – Niklas B. Mar 03 '12 at 21:09
  • @Niklas B. It could be a Good Thing. The standard way grows the hash if you just want to know the anagrams of h[:not_a_key]. But `h[:not_a_key] << 1` being silently discarded is a certainly a good argument. – steenslag Mar 03 '12 at 21:22