# Strange behaviour

**URL:** <https://www.ruby-forum.com/t/strange-behaviour/79994>\
**Category:** Ruby\
**Created:** [March 12, 2006, 12:28am UTC](https://www.ruby-forum.com/t/strange-behaviour/79994 "2006-03-12T00:28:21Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![javier\_v](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/7bcc69/32.png) [@javier\_v](https://www.ruby-forum.com/u/javier_v)\
**Post date:** [March 12, 2006, 12:28am UTC](https://www.ruby-forum.com/t/strange-behaviour/79994/1 "2006-03-12T00:28:21Z")

</div>

Look this:

tigre@enigma tigre $ irb  
irb(main):001:0\> events = {}  
=\> {}  
irb(main):002:0\> events.default = []  
=\> []  
irb(main):003:0\> events[“trying”] \<\< “hello”  
=\> [“hello”]  
irb(main):004:0\> events  
=\> {}  
irb(main):005:0\> events.inspect  
=\> “{}”  
irb(main):006:0\> events[“trying”]  
=\> [“hello”]  
irb(main):007:0\> quit  
tigre@enigma tigre $

why is happening this behaviour?

---

<div class="post-metadata">

**Author:** ![javier\_v](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/7bcc69/32.png) [@javier\_v](https://www.ruby-forum.com/u/javier_v)\
**Post date:** [March 12, 2006, 1:04am UTC](https://www.ruby-forum.com/t/strange-behaviour/79994/2 "2006-03-12T01:04:46Z")

</div>

On 3/11/06, Javier V. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> =\> “{}”  
> irb(main):006:0\> events[“trying”]  
> =\> [“hello”]  
> irb(main):007:0\> quit  
> tigre@enigma tigre $
> 
> why is happening this behaviour?

Take a look at this for some clues:

$ irb  
irb(main):001:0\> events = {}  
=\> {}  
irb(main):002:0\> events.default = []  
=\> []  
irb(main):003:0\> events[“trying”] \<\< “hello”  
=\> [“hello”]  
irb(main):004:0\> events.default  
=\> [“hello”]  
irb(main):005:0\> events[“test”]  
=\> [“hello”]

In short, what’s happening is that when you call events[“trying”] at  
statement 3, it returns the default value, which is an array. You then  
insert “hello” into that array and _change the default value_. Since  
you never assigned to events[“trying”], it still doesn’t exist. You  
were only getting the expected value back on re-access because of the  
changed default value.

Try this instead:

$ irb  
irb(main):001:0\> events = Hash.new{ |h,k| h[k] = [] }  
=\> {}  
irb(main):002:0\> events.default  
=\> []  
irb(main):003:0\> events[“trying”] \<\< “hello”  
=\> [“hello”]  
irb(main):004:0\> events.default  
=\> []  
irb(main):005:0\> events[“trying”]  
=\> [“hello”]  
irb(main):006:0\> events[“test”]  
=\> []  
irb(main):007:0\> events  
=\> {nil=\>[], “test”=\>[], “trying”=\>[“hello”]}

This produces the desired behavior, but you have to be careful, since  
accessing non-existent keys will pollute the keys of your hash.

---

<div class="post-metadata">

**Author:** ![javier\_v](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/7bcc69/32.png) [@javier\_v](https://www.ruby-forum.com/u/javier_v)\
**Post date:** [March 12, 2006, 1:10am UTC](https://www.ruby-forum.com/t/strange-behaviour/79994/3 "2006-03-12T01:10:50Z")

</div>

> =\> [“hello”]  
> Try this instead:  
> irb(main):005:0\> events[“trying”]  
> Jacob F.

Oh thanks, i really had a misunderstood on that point.

---

<div class="post-metadata">

**Author:** ![javier\_v](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/7bcc69/32.png) [@javier\_v](https://www.ruby-forum.com/u/javier_v)\
**Post date:** [March 12, 2006, 1:19am UTC](https://www.ruby-forum.com/t/strange-behaviour/79994/4 "2006-03-12T01:19:54Z")

</div>

Javier V. wrote:

> =\> {}

The “events.default = []” statement establishes a default object to be  
returned when you access a key that is not in the hash. The same object  
is always returned. That is, the same array will be returned every time  
you access a key that is not in the hash. Further, adding an element to  
that array by fetching a non-existent key does not add the key to the  
hash. The ‘events[“trying”] \<\< “hello”’ statement sends [] to the hash,  
which returns the default array, then adds “hello” to the array. To add  
a key to the hash you have to use its []= method\*.

Look at this sequence for example:

irb(main):001:0\> ary = []  
=\> []  
irb(main):002:0\> hsh = {}  
=\> {}  
irb(main):003:0\> hsh.default = ary  
=\> []  
irb(main):004:0\> hsh[:a] \<\< 1  
=\> [1]  
irb(main):005:0\> hsh  
=\> {}  
irb(main):006:0\> ary  
=\> [1]  
irb(main):007:0\> hsh[:b] = 1  
=\> 1  
irb(main):008:0\> hsh  
=\> {:b=\>1}

\*Okay, for the picky, there’s other ways to add a key to a hash. Work  
with me here.

---

<div class="post-metadata">

**Author:** ![javier\_v](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/7bcc69/32.png) [@javier\_v](https://www.ruby-forum.com/u/javier_v)\
**Post date:** [March 12, 2006, 1:13am UTC](https://www.ruby-forum.com/t/strange-behaviour/79994/5 "2006-03-12T01:13:52Z")

</div>

This stems from a fundamental misunderstanding of how the default  
attribute of a hash is used by the hash.

On Sun, Mar 12, 2006 at 08:26:05AM +0900, Javier V. wrote:  
} Look this:  
}  
} tigre@enigma tigre $ irb  
} irb(main):001:0\> events = {}  
} =\> {}

The events variable has been set to a new instance of a hash.

} irb(main):002:0\> events.default = []  
} =\> []

The events.default attribute has been set to a new instance of an array.

} irb(main):003:0\> events[“trying”] \<\< “hello”  
} =\> [“hello”]

The array in the events.default attribute is retrieved, since “trying”  
is  
not a key in the hash, and has “hello” appended to it.

} irb(main):004:0\> events  
} =\> {}

The events variable continues to hold an empty hash, which has a default  
attribute set to [“hello”].

} irb(main):005:0\> events.inspect  
} =\> “{}”

Still empty.

} irb(main):006:0\> events[“trying”]  
} =\> [“hello”]

The events.default attribute is retrieved since “trying” is not a key in  
the hash. The attribute is an array which has previously had “hello”  
appended to it.

} why is happening this behaviour?

This is correct behavior. The default attribute is not the default  
starting  
value for any key, it is the value returned when a key is not found. See  
the following:

irb(main):001:0\> events = {}  
=\> {}  
irb(main):002:0\> events.default = []  
=\> []  
irb(main):003:0\> events[“trying”] \<\< “hello”  
=\> [“hello”]  
irb(main):004:0\> events[“nosuchkey”]  
=\> [“hello”]  
irb(main):005:0\> events.default  
=\> [“hello”]  
irb(main):006:0\> events.default.object\_id  
=\> 403034172  
irb(main):007:0\> events[“trying”].object\_id  
=\> 403034172  
irb(main):008:0\> events[“nosuchkey”].object\_id  
=\> 403034172
