From: "Derrick B." Date: 2012-12-29T02:17:49+09:00 Subject: Re: Ruby Koans regarding Hashes. 7stud -- wrote in post #1090450: > > 1) You never write > > Hash.new([]) > > .. (or with any other mutable type as the argument) because the same > array is the default for every key, and that is never useful. > That makes sense, and I got that same uselessness feeling when I saw the assertions made against different indexes. > > This is what you want: > > hash = Hash.new {|hash, key| hash[key] = []} > > hash[:one] << 'hello' > hash[:two] << 'goodbye' > > p hash > > --output:-- > {:one=>["hello"], :two=>["goodbye"]} > That was actually the very next test block in that "about_hashes.rb" Koans file: def test_default_value_with_block hash = Hash.new {|hash, key| hash[key] = [] } hash[:one] << "uno" hash[:two] << "dos" assert_equal ["uno"], hash[:one] assert_equal ["dos"], hash[:two] assert_equal [], hash[:three] end > > In this case, the block executes *every time* you access a > non-existent key, and the block creates a new array > and assigns it to the key, *and* the return value is a > reference to the array that was assigned to the key. > As a result, all you need to do is append to the array. > This is one of those "I get it, but then I do not get it" paradoxes. I understand whatever is returned from the block is assigned to "hash", right? So, inside the block, a hash key is generated with an array as its value: hash[key] = [] But, since an append method was used, the value being appended, in this case "uno" or "dos", now becomes the value for whatever key index, :one or :two, is provided: hash[:one] = ["uno"] Since the block is executed every time, a new array object is created, so each key has different array object id. So this: hash = hash[:one] = ["uno"] Did this: Unique array id ([]), appended with a string ("uno"), assigned to hash key (:one), assigned to variable (hash). > It can be useful to use the first type of hash creator with non-mutable > types as an argument: > > hash = Hash.new 0 > > hash[:one] += 1 > hash[:two] += 1 > > p hash > > --output:-- > {:one=>1, :two=>1} Or as an accumulator: >> hash = Hash.new 0 => {} >> hash[:one] => 0 >> hash[:one] += 1 => 1 >> hash[:one] => 1 >> hash[:one] += 1 => 2 >> hash[:one] += 1 => 3 >> hash[:one] += 1 => 4 ...which I currently have no idea how that could be useful, but it is still interesting... heh Looks like I am not the only one that found that Ruby Koans lesson a bit confusing: http://stackoverflow.com/questions/9537714/rubykoans-confusing-hash-example http://stackoverflow.com/questions/9343680/how-does-shovel-operator-work-in-ruby-hashes/9343737#9343737 Thanks, that helped clear some things up. -- Posted via http://www.ruby-forum.com/.