Alex Rivera | Logout

Is the ruby operator ||= intelligent?

Asked 2010-06-07T13:22:29.803
17

I have a question regarding the ||= statement in ruby and this is of particular interest to me as I'm using it to write to memcache. What I'm wondering is, does ||= check the receiver first to see if it's set before calling that setter, or is it literally an alias to x = x || y

This wouldn't really matter in the case of a normal variable but using something like:

CACHE[:some_key] ||= "Some String"

could possibly do a memcache write which is more expensive than a simple variable set. I couldn't find anything about ||= in the ruby api oddly enough so I haven't been able to answer this myself.

Of course I know that:

CACHE[:some_key] = "Some String" if CACHE[:some_key].nil?

would achieve this, I'm just looking for the most terse syntax.

Edit
Report

1 Answer

7

According to §11.3.1.2.2 of the Draft ISO Specification,

CACHE[:some_key] ||= "Some String"

expands to

o = CACHE
*l = :some_key
v = o.[](*l)
w = "Some String"
x = v || w
l << x
o.[]=(*l)
x

Or, in the more general case

primary_expression[indexing_argument_list] ω= expression

(I am using ω here to denote any operator, so it could be ||=, +=, *=, >>=, %=,…)

Expands to:

o = primary_expression
*l = indexing_argument_list
v = o.[](*l)
w = expression
x = v ω w
l << x
o.[]=(*l)
x

So, according to the specification, []= will always get called. But that is actually not the case in current implementations (I tested MRI, YARV, Rubinius, JRuby and IronRuby):

def (h = {}).[]=(k, v) p "Setting #{k} to #{v}"; super end
h[:key] ||= :value # => :value
# "Setting key to value"
h[:key] ||= :value # => :value

So, obviously either the specification is wrong or all five currently released implementations are wrong. And since the purpose of the specification is to describe the behavior of the existing implementations, it's obviously that the specification must be wrong.

In general, as a first approximation

a ||= b

expands to

a || a = b

However, there's all kinds of subleties involved, for example, whether or not a is undefined, whether a is a simple variable or a more complex expression like foo[bar] or foo.bar and so on.

See also some of the other instances of this same question, that have already been asked and answered here on StackOverflow (for example, answered 2010-06-07T15:18:02.897

Your Answer