8

Possible Duplicate:
What does ||= mean in Ruby?

what does the below line mean?

a ||= {} 
a ||= 1

in irb it always returns the class of a, as hash, for both the above lines. Thanks in advance.

Community
  • 1
  • 1
doel
  • 81
  • 1
  • 2
  • @mladen True, but personally I'd vote to close the other question in favour of this one. This one has more up to date/correct information in the top rated answer. – Matthew Scharley Mar 08 '11 at 13:37
  • Duplicate: [What does `||=` mean in Ruby?](http://StackOverflow.Com/q/995593/), [What does `||=` mean in Ruby?](http://StackOverflow.Com/q/3800957/), [what is `||=` in ruby?](http://StackOverflow.Com/q/3945711/), [Double Pipe Symbols in Ruby Variable Assignment?](http://StackOverflow.Com/q/4500375/), [What does the “`||=`” operand stand for in ruby](http://StackOverflow.Com/q/5124930/), [Is the ruby operator `||=` intelligent?](http://StackOverflow.Com/q/2989862/) and probably many others as well. – Jörg W Mittag Mar 08 '11 at 17:34
  • See also [The definitive list of `||=` (OR Equal) threads and pages](http://Ruby-Forum.Com/topic/151660/). [What does `||=` mean in Ruby?](http://StackOverflow.Com/q/995593/) and [What does `||=` mean in Ruby?](http://StackOverflow.Com/q/3800957/) are even linked to under *Related Questions*. – Jörg W Mittag Mar 08 '11 at 17:35

3 Answers3

16

||= is an assignment operator, which returns the value assigned. a ||= b is equivalent to the statement a || a = b which means that if a is set and has some true value, then it remains the same, otherwise it takes the value of b.

In your example a is only ever set once, which explains the behaviour you've noticed.

a ||= {} 
a ||= 1 // a is still {}

Typical usage I've seen is to initialise static variables, ie.

class Foo
    def self.bar
        return @bar ||= {}
    end
end

EDIT:

It bears mentioning that ||= is a short-circuit operator. This means that it in the case of a ||= b there will only be an assignment of a = b. There will never be an assignment of a = a in the case that a is non-false. This is a little pedantic, but matters in some (very) edge cases.

For more information, read the definitive list of ||= threads and pages.

Matthew Scharley
  • 127,823
  • 52
  • 194
  • 222
  • Your example is an instance variable, not a static (or class) variable. That would be `@@something`. [still the best answer :)] – Simon Woker Mar 08 '11 at 08:54
  • @Simon Just noticed the same thing. Fixed now (though, not quite your way). – Matthew Scharley Mar 08 '11 at 08:55
  • It is also frequently used to check-assign stuff in Hashes (à-la: `hash[key] ||= initial_value`, especially if what you want to do next is `hash[key] += value`, which would error if `hash[key].nil?` is true-ish). – Romain Mar 08 '11 at 09:16
  • 1
    @Romain Ironically, that is exactly the edge case where the fact it's a short-circuit operator matters. http://dablog.rubypal.com/2008/3/25/a-short-circuit-edge-case – Matthew Scharley Mar 08 '11 at 13:36
  • @Matthew Yep, this is indeed something one would not notice in 99.9% of cases, though it can come in handy from time to time... Also, the article you point to formalizes as `x ||= a` as `x || x = a`, which is how I usually interpret the or-assignment. – Romain Mar 09 '11 at 11:10
  • Interesting to read the argument that `a ||= b` is equivalent to `a || a = b`, not `a = a || b`, as you would expect (and as the `+=` operator would suggest). – Edd Steel Mar 09 '11 at 13:26
  • @Edd Steel It's a very minor distinction. In the case of say `+=` there has to always be an assignment as an addition will always evaluate to something. In the case of a logic operator, I think it does make sense to short circuit the assignment version since the original is a short circuit too. ie, for `a || b`, `b` will never be evaluated if `a` is trueish. – Matthew Scharley Mar 09 '11 at 14:07
  • Proper way to initialize a class-instance-variable would be to just assign to it in the class body. For your example, that'd be: `class Foo; @bar = {}; end` – apeiros Aug 12 '13 at 15:46
  • @apeiros Except that the version in my answer in lazy-loaded which is sometimes desirable and sometimes even required. – Matthew Scharley Aug 12 '13 at 21:00
  • @MatthewScharley Except that a) the example used an empty Hash which is totally not a use case for lazy loading and b) that lazy loading values itself is a universal concept and not directly related to the question of class ivar initialization. – apeiros Aug 16 '13 at 18:42
0

It means

a = a || {}

i.e.

a = {} unless a
Dom De Felice
  • 476
  • 4
  • 10
0

you can read "a ||= {}" like this. If "a" is defined, then ignore the expression on the right side. Else, set "a" equals to the expression on the right side. In the first line, "a" is probably undefined so that line sets "a" to the expression on the right which is the empty hash. On the second line, "a" is already set as a {} so it is ignoring the expression on the right which has a value of 1.

RubyFanatic
  • 2,241
  • 3
  • 22
  • 35