# Hash default -- what's going on here?

**URL:** <https://www.ruby-forum.com/t/hash-default-whats-going-on-here/82114>\
**Category:** Ruby\
**Created:** [March 15, 2006, 8:10am UTC](https://www.ruby-forum.com/t/hash-default-whats-going-on-here/82114 "2006-03-15T08:10:27Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [March 15, 2006, 8:10am UTC](https://www.ruby-forum.com/t/hash-default-whats-going-on-here/82114/1 "2006-03-15T08:10:27Z")

</div>

I’ve hit what is either an egregious bug in ruby (1.8.4) or some  
subtlety  
that I haven’t grasped. [Most likely the latter… (:-)]

Briefly I had two arrays of symbol strings of which I wanted to find  
which symbols occurred in both arrays, so I thought I’d use a hash with  
the key being the symbol and the value a two element array that would  
be used to flag which set(s) the symbol was found in. The following  
is a simplified (and ‘instrumented’) version of what I was trying to  
do:

listA=[“line1”,“line2”,“line3”]  
listB=[“line5”,“line3”,“line4”]  
table={}  
table.default=[0,0]  
print "table default originally: ", table.default, “\n”

listA.each {|a| t=table[a]; print a," – undef value: “,t;  
t[0]=1; print " new value: “,t,”\n”;  
table[a]=t}  
print "table default now: ", table.default, “\n”

listB.each {|a| t=table[a]; print a," – undef value: “,t;  
t[1]=1; print " new value: “,t,”\n”;  
table[a]=t}

print "table default now: ", table.default, “\ntable contents:\n”  
table.each {|k,v| print k, ": ", v[0], v[1], “\n”}

Now, in the ‘each’ statements, the variable ‘a’ should (except in one  
case)  
not be in the hash yet, so I would expect the original provided default  
to  
be returned. However, here’s the printout I get:

table default now: 00  
line1 – undef value: 00 new value: 10  
line2 – undef value: 10 new value: 10  
line3 – undef value: 10 new value: 10  
table default now: 10  
line5 – undef value: 10 new value: 11  
line3 – undef value: 11 new value: 11  
line4 – undef value: 11 new value: 11  
table default now: 11  
table contents:  
line1: 11  
line2: 11  
line3: 11  
line4: 11  
line5: 11

Dunhh? Why is the default value getting changed? I can’t see that  
I’m resetting it anywhere. If I do the same sort of manipulations  
outside of a block (one at a time in irb for instance) things happen  
as I would expect – the default remains as set, and is returned for  
any undefined key.

Illumination appreciated.  
– Pete –

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [March 15, 2006, 8:19am UTC](https://www.ruby-forum.com/t/hash-default-whats-going-on-here/82114/2 "2006-03-15T08:19:35Z")

</div>

I’m guessing it’s got something to do with your assignment

```
                    table[a]=t

```

the array that is the hash’s default can be assigned to. I think that’s  
what you’re doing. If i did some testing I might be more sure 🙂

;Daniel

On 15/03/06, Pete G. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> do:  
> print "table default now: ", table.default, “\n”  
> case)  
> line4 – undef value: 11 new value: 11  
> I’m resetting it anywhere. If I do the same sort of manipulations  
> outside of a block (one at a time in irb for instance) things happen  
> as I would expect – the default remains as set, and is returned for  
> any undefined key.
> 
> Illumination appreciated.  
> – Pete –

–  
Daniel B.  
[http://danielbaird.com](http://danielbaird.com) (TiddlyW;nks! :: Whiteboard Koala :: Blog ::  
Things  
That Suck)  
[[My webhost uptime is ~ 92%… if no answer pls call again later!]]

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [March 15, 2006, 10:09am UTC](https://www.ruby-forum.com/t/hash-default-whats-going-on-here/82114/3 "2006-03-15T10:09:29Z")

</div>

In article [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid),  
Daniel B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> what you’re doing. If i did some testing I might be more sure 🙂

Heh – you can tell I’m new to ruby… (:-))

An hour after I posted I suddenly realized what is going on.  
When you assign an array, the array is _not_ copied! the assigned-to  
variable just gets a pointer to the other array.

So when I did “t=table[a]” I was setting t to a pointer to the default!  
When I changed t[n], of course the default was actually what got  
changed…

Sigh. Hardly a novel gotcha, but I fell right into it.

Not sure of the best way to do what I want – maybe just use ‘has\_key?’  
and then do the right thing.  
– Pete –

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [March 15, 2006, 3:29pm UTC](https://www.ruby-forum.com/t/hash-default-whats-going-on-here/82114/4 "2006-03-15T15:29:44Z")

</div>

“Pete G.” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote in message  
news:dv8lhf$18m$removed\_email\_address@domain.invalid…

> Not sure of the best way to do what I want – maybe just use ‘has\_key?’  
> and then do the right thing.

The question is what exactly are you trying to do?

```
robert

```

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [March 15, 2006, 8:41am UTC](https://www.ruby-forum.com/t/hash-default-whats-going-on-here/82114/5 "2006-03-15T08:41:01Z")

</div>

2006/3/15, Pete G. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> listA=[“line1”,“line2”,“line3”]  
> listB=[“line5”,“line3”,“line4”]  
> table={}

Here’s the problem:

> table.default=[0,0]

What you are looking for is:

table = Hash.new { |h, k| h[k] = [0, 0] }

otherwise you are always pointing to _the same_ object
