79 def test_default_value
80 hash1 = Hash.new
81 hash1[:one] = 1
82
83 assert_equal 1, hash1[:one]
84 assert_equal nil, hash1[:two]
85
86 hash2 = Hash.new("dos")
87 hash2[:one] = 1
88
89 assert_equal 1, hash2[:one]
90 assert_equal "dos", hash2[:two]
91 end
92
93 def test_default_value_is_the_same_object
94 hash = Hash.new([])
95
96 hash[:one] << "uno"
97 hash[:two] << "dos"
98
99 assert_equal ["uno","dos"], hash[:one]
100 assert_equal ["uno","dos"], hash[:two]
101 assert_equal ["uno","dos"], hash[:three]
102
103 assert_equal true, hash[:one].object_id == hash[:two].object_id
104 end
105
106 def test_default_value_with_block
107 hash = Hash.new {|hash, key| hash[key] = [] }
108
109 hash[:one] << "uno"
110 hash[:two] << "dos"
111
112 assert_equal ["uno"], hash[:one]
113 assert_equal ["dos"], hash[:two]
114 assert_equal [], hash[:three]
115 end
It's easy to cheat and get these to pass, but I want to know what is going on, specifically in lines: 86, 90, 94, 96/97, 109/110, and 114.
Time for some research!
So, doing this, hash = Hash.new("dos"), means that "dos" will be used for all default values in that hash.
That explains line 90 and why the correct value is "dos", rather than nil, like I originally thought. Turns out if we don't provide a default value, nil is what you'll get. Makes sense, I guess.
So then on line 94, we are setting the default value to an empty array. What I forgot before was that << is pushing a value onto an array. In this case, the empty arrays that are the values associated with the keys: :one and :two. Cool, it makes sense!
This brings us to line 114. It is related to how this hash was created on line 107. In this case, it was created with a block. This is defaulting the value to an empty array each time, but would pay attention to the value of the key if you pass one in.
The docs are good and illustrate the difference:
h = Hash.new("Go Fish") h["a"] = 100 h["b"] = 200 h["a"] #=> 100 h["c"] #=> "Go Fish" # The following alters the single default object h["c"].upcase! #=> "GO FISH" h["d"] #=> "GO FISH" h.keys #=> ["a", "b"] # While this creates a new default object each time h = Hash.new { |hash, key| hash[key] = "Go Fish: #{key}" } h["c"] #=> "Go Fish: c" h["c"].upcase! #=> "GO FISH: C" h["d"] #=> "Go Fish: d" h.keys #=> ["c", "d"]
Wow, I think I just learned some things here, but the trick will be to remember them.
No comments:
Post a Comment