# Odd behavior when \<\< hash

**URL:** <https://www.ruby-forum.com/t/odd-behavior-when-hash/195410>\
**Category:** Ruby\
**Created:** [September 22, 2010, 9:34pm UTC](https://www.ruby-forum.com/t/odd-behavior-when-hash/195410 "2010-09-22T21:34:05Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![asoto](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/58956e/32.png) [@asoto](https://www.ruby-forum.com/u/asoto)\
**Post date:** [September 22, 2010, 9:34pm UTC](https://www.ruby-forum.com/t/odd-behavior-when-hash/195410/1 "2010-09-22T21:34:05Z")

</div>

Hi Folks - Using Ruby 1.8.7, I found this oddity:

require ‘rubygems’  
require ‘json’

setup = []  
ids = [“12345”, “54321”, “21345”, “548752”, “3215”, “50203”]

doIt = {  
“action” =\> “do something”,  
“result” =\> “true”  
}

cnt = rand(10)  
1.upto(cnt) do

doIt[‘params’] = ids[rand(6)]  
p “Pushing step: #{doIt.inspect}”  
setup \<\< doIt  
end

p “Final steps list: #{setup.inspect}”

* * *

When I inspect my final steps list at the end, the values of  
‘doIt[‘params’]’ is always the same - set to the last value of the last  
run of the upto loop. But when I inspect doIt prior to pushing it, I  
can see that it has its own value, acquired randomly.

So my question is, why is the hash not being pushed onto the array  
properly? What side effect am I encountering here and how do I get  
around it?

(I’ve already tried declaring “params” =\> “” in the initial hash  
creation; that didn’t help).

Thanks,  
Alex

PS - You’d be correct in noting this code doesn’t do anything useful.  
I’ve stripped away other parts to isolate the questionable behavior for  
demonstration purposes.

---

<div class="post-metadata">

**Author:** ![asoto](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/58956e/32.png) [@asoto](https://www.ruby-forum.com/u/asoto)\
**Post date:** [September 22, 2010, 9:44pm UTC](https://www.ruby-forum.com/t/odd-behavior-when-hash/195410/2 "2010-09-22T21:44:03Z")

</div>

On Sep 22, 2010, at 3:33 PM, Alex S. wrote:

> “result” =\> “true”  
> }

# so here, doIt is referencing an object which is a hash

> cnt = rand(10)  
> 1.upto(cnt) do
> 
> doIt[‘params’] = ids[rand(6)]  
> p “Pushing step: #{doIt.inspect}”  
> setup \<\< doIt

# this puts that reference into the setup array

# NOTE: it is always referring to the same hash

> can see that it has its own value, acquired randomly.
> 
> PS - You’d be correct in noting this code doesn’t do anything useful.  
> I’ve stripped away other parts to isolate the questionable behavior  
> for  
> demonstration purposes.

Try creating the hash object inside the loop (i.e., creating a new  
object each time)

rand(10).times do  
setup \<\< { “action” =\> “do something”,  
“result” =\> “true”,  
“params” =\> ids[rand(6)].dup  
}  
end  
puts “Final steps list: #{setup.inspect}”

Note that I’m also calling .dup on the element taken from the ids  
array so there’s a separate string object. You can apply this to your  
real code, I hope.

-Rob

Rob B.  
removed\_email\_address@domain.invalid [http://AgileConsultingLLC.com/](http://AgileConsultingLLC.com/)  
removed\_email\_address@domain.invalid [http://GaslightSoftware.com/](http://GaslightSoftware.com/)

---

<div class="post-metadata">

**Author:** ![asoto](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/58956e/32.png) [@asoto](https://www.ruby-forum.com/u/asoto)\
**Post date:** [September 22, 2010, 9:52pm UTC](https://www.ruby-forum.com/t/odd-behavior-when-hash/195410/3 "2010-09-22T21:52:14Z")

</div>

Thanks, Rob. Made the mistake of assuming I get a copy of the hash when  
I push it. IIRC, there are other (not-so-elegant) languages that do so.

Appreciate the point about .dup as well, but since at the end of this,  
I’m just writing everything out to a file, and the elements of ids will  
never change (at least not in this script), I don’t think I need a  
duplicate string.

---

<div class="post-metadata">

**Author:** ![asoto](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/58956e/32.png) [@asoto](https://www.ruby-forum.com/u/asoto)\
**Post date:** [September 22, 2010, 9:54pm UTC](https://www.ruby-forum.com/t/odd-behavior-when-hash/195410/4 "2010-09-22T21:54:00Z")

</div>

On Wed, Sep 22, 2010 at 2:33 PM, Alex S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> “result” =\> “true”  
> p “Final steps list: #{setup.inspect}”  
> around it?

You are modifying the same hash, then adding the same hash to the array  
again. In other words, there is only ever one hash in your program (and  
data  
is mutable in Ruby).

To analogize, if you record my address ten times, painting my shutters a  
different after each, then decide to visit each of the ten addresses  
that  
you have written down, you will find that all of the houses you visit  
will  
have the same colour of shutters as the final time you painted my house.

I have modified the program to hopefully make this clearer.  
[http://codepad.org/ZPB7UC6Q](http://codepad.org/ZPB7UC6Q)

---

<div class="post-metadata">

**Author:** ![asoto](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/58956e/32.png) [@asoto](https://www.ruby-forum.com/u/asoto)\
**Post date:** [September 23, 2010, 8:28am UTC](https://www.ruby-forum.com/t/odd-behavior-when-hash/195410/5 "2010-09-23T08:28:58Z")

</div>

On 22.09.2010 21:51, Alex S. wrote:

> Thanks, Rob. Made the mistake of assuming I get a copy of the hash when  
> I push it. IIRC, there are other (not-so-elegant) languages that do so.
> 
> Appreciate the point about .dup as well, but since at the end of this,  
> I’m just writing everything out to a file, and the elements of ids will  
> never change (at least not in this script), I don’t think I need a  
> duplicate string.

To complement the excellent explanations you have been given already:  
the technical term for the effect is “aliasing”.

> **[Aliasing (computing) | Aliased pointers](https://en.wikipedia.org/wiki/Aliasing_(computing)#Aliased_pointers)**
>
> Another variety of aliasing can occur in any language that can refer to one location in memory with more than one name (for example, with pointers). See the C example of the XOR swap algorithm that is a function; it assumes the two pointers passed to it are distinct, but if they are in fact equal (or aliases of each other), the function fails. This is a common problem with functions that accept pointer arguments, and their tolerance (or the lack thereof) for aliasing must be carefully documented,...

Kind regards

robert
