# Question about abbreviated indexing assignments

**URL:** <https://www.ruby-forum.com/t/question-about-abbreviated-indexing-assignments/189781>\
**Category:** Ruby\
**Created:** [June 7, 2010, 5:45pm UTC](https://www.ruby-forum.com/t/question-about-abbreviated-indexing-assignments/189781 "2010-06-07T17:45:57Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![JSSSSrg\_W\_Mittag](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/ecb155/32.png) [@JSSSSrg\_W\_Mittag](https://www.ruby-forum.com/u/JSSSSrg_W_Mittag)\
**Post date:** [June 7, 2010, 5:45pm UTC](https://www.ruby-forum.com/t/question-about-abbreviated-indexing-assignments/189781/1 "2010-06-07T17:45:57Z")

</div>

Hi!

According to the specification,

primary\_expression[indexing\_argument\_list] Ï‰= expression

is (roughly) evaluated like

o = primary\_expression  
\*l = indexing\_argument\_list  
v = o.  
w = expression  
(v Ï‰ w).tap {|x|  
l \<\< x  
o.[]=(\*l)  
}

In particular, this means that the assignment _always_ takes place.  
However, at least in some Ruby implementations (I tested MRI, YARV,  
Rubinius, JRuby and IronRuby), this doesn’t actually seem to be the  
case, at least for some operators:

def (h = {int: 0}).[]=(k, v) p “Setting #{k} to #{v}”; super end  
h[:int] += 1

# “Setting int to 1”

h[:int] += 1

# “Setting int to 2”

This calls the setter twice, as expected per the specification.

h[:key] ||= :value

# “Setting key to value”

h[:key] ||= :value

But this doesn’t.

Since the purpose of the specification is to describe the currently  
existing implementations, this is obviously a bug in the specification  
rather than a bug in all five currently released implementations,  
especially since there is a ton of code and even a common idiom that  
depends on the current behavior. But what would the correct  
specification look like?

Thanks in advance,  
JÃ¶rg.

---

<div class="post-metadata">

**Author:** ![JSSSSrg\_W\_Mittag](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/ecb155/32.png) [@JSSSSrg\_W\_Mittag](https://www.ruby-forum.com/u/JSSSSrg_W_Mittag)\
**Post date:** [June 7, 2010, 7:06pm UTC](https://www.ruby-forum.com/t/question-about-abbreviated-indexing-assignments/189781/2 "2010-06-07T19:06:11Z")

</div>

On 2010-06-07 08:42:08 -0700, Jörg W Mittag said:

> depends on the current behavior. But what would the correct  
> specification look like?
> 
> Thanks in advance,  
> Jörg.

It is commonly thought that x = y is exactly equivalent to x  
= x y in all cases. What you have just demonstrated is that,  
presumably for performance reasons, h[key] ||= value is in fact  
equivalent to h[key] || h[key] = value, rather than h[key] = h[key] ||  
value. This prevents a second lookup in the case where k[key] exists  
and is not nil or false.

As to what the correct specification would look like, I am not sure,  
but I do agree with you.

---

<div class="post-metadata">

**Author:** ![JSSSSrg\_W\_Mittag](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/ecb155/32.png) [@JSSSSrg\_W\_Mittag](https://www.ruby-forum.com/u/JSSSSrg_W_Mittag)\
**Post date:** [June 7, 2010, 9:19pm UTC](https://www.ruby-forum.com/t/question-about-abbreviated-indexing-assignments/189781/3 "2010-06-07T21:19:04Z")

</div>

On Mon, Jun 7, 2010 at 1:05 PM, Rein H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> It is commonly thought that x = y is exactly equivalent to x = x  
> y in all cases. What you have just demonstrated is that,  
> presumably for performance reasons, h[key] ||= value is in fact equivalent  
> to h[key] || h[key] = value, rather than h[key] = h[key] || value. This  
> prevents a second lookup in the case where k[key] exists and is not nil or  
> false.

x ||= y is NOT equivalent to x = x || y

Instead a closer approximation is

x || x = y

[http://talklikeaduck.denhaven2.com/2008/04/26/x-y-redux](http://talklikeaduck.denhaven2.com/2008/04/26/x-y-redux)

–  
Rick DeNatale

Blog: [http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)  
Github: [rubyredrick (Rick DeNatale) · GitHub](http://github.com/rubyredrick)  
Twitter: @RickDeNatale  
WWR: [http://www.workingwithrails.com/person/9021-rick-denatale](http://www.workingwithrails.com/person/9021-rick-denatale)  
LinkedIn: [http://www.linkedin.com/in/rickdenatale](http://www.linkedin.com/in/rickdenatale)

---

<div class="post-metadata">

**Author:** ![JSSSSrg\_W\_Mittag](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/ecb155/32.png) [@JSSSSrg\_W\_Mittag](https://www.ruby-forum.com/u/JSSSSrg_W_Mittag)\
**Post date:** [June 7, 2010, 10:30pm UTC](https://www.ruby-forum.com/t/question-about-abbreviated-indexing-assignments/189781/4 "2010-06-07T22:30:33Z")

</div>

On 2010-06-07 12:18:39 -0700, Rick DeNatale said:

> Instead a closer approximation is
> 
> x || x = y
> 
> [http://talklikeaduck.denhaven2.com/2008/04/26/x-y-redux](http://talklikeaduck.denhaven2.com/2008/04/26/x-y-redux)

Good explanation in that post, Rick. Thanks!
