Logical OR in Ruby

I’m looking at some source code, to try and understand it.

There’s a variable “weight”, and then there’s this call:

weight ||= 100

which I take to be equivalent to:

weight = weight || 100

(i.e., performing a logical OR between “weight” and 100).

What I think this code means, is that the value that will be assigned to
“weight” will be either (a) “weight” (if weight has already been
assigned) or else (b) if “weight” is presently nil, then the value 100
will be assigned to “weight” instead.

Is this correct?

On Sun, Mar 20, 2011 at 10:09 PM, Paul S. [email protected]
wrote:

(i.e., performing a logical OR between “weight” and 100).

What I think this code means, is that the value that will be assigned to
“weight” will be either (a) “weight” (if weight has already been
assigned) or else (b) if “weight” is presently nil, then the value 100
will be assigned to “weight” instead.

Is this correct?

yes.

Generally, you’ll find irb to be very helpful in finding things like
this out:

irb(main):001:0> foo ||= 10
=> 10
irb(main):002:0> foo
=> 10
irb(main):003:0> foo ||=100
=> 10
irb(main):004:0> foo
=> 10
irb(main):005:0>

More specifically, || returns the second operand when the first operand
is “falsy” -
logically false. Both nil and false are logically false.

So if “weight” were either nil OR false, then it would be reassigned.

Michael E.
[email protected]
http://carboni.ca/

On Mon, Mar 21, 2011 at 4:09 AM, Paul S. [email protected]
wrote:

I’m looking at some source code, to try and understand it.
There’s a variable “weight”, and then there’s this call:
weight ||= 100
which I take to be equivalent to:
weight = weight || 100
(i.e., performing a logical OR between “weight” and 100).

Not quite correct. there’s a useful explanation here:
http://talklikeaduck.denhaven2.com/2008/04/26/x-y-redux
which (providing I’m reading Rick DeNatale’s blog correctly) tells us
that
(weight ||= 100) is expanded in Ruby as (weight || (weight = 100))
which mostly is the same as (weight = (weight || 100)), but might be
different (to quote Rick DeNatale) “when the left hand side is a
method call, to an accessor, or accessor-like method”.

*** an extract from Rick DeNatale’s blog post:

Matz explains that the real expansion of x ||= y is: x || x = y

The expectation that x ||= y is the same as x = x || y, does seem
reasonable to someone coming from C or one of its derivative
languages. As far as I can determine, C introduced the notion of
assignment operators like += and -=. And K&R defined these assignment
operators as a shorthand for x = x + y, etc.

On the other hand, although C has logical operators || and && which,
like Ruby have short-circuit evaluation, it doesnt allow ||=, or
&&= as assignment operators.

Since || is a short-circuit boolean operator, the right hand operand
expression is only evaluated if the left hand operand expression
evaluates to a logically false value, i.e. either nil or false.

The way that Matz included ||= as an assignment operator makes perfect
sense to me. The ||= assignment operator reserves the short-circuit
nature of ||.

*** Rick DeNatale also points out that &&= has similar behaviour.

On 21/03/2011 5.09, Paul S. wrote:

I’m looking at some source code, to try and understand it.

[snip]

What I think this code means, is that the value that will be assigned to
“weight” will be either (a) “weight” (if weight has already been
assigned) or else (b) if “weight” is presently nil, then the value 100
will be assigned to “weight” instead.

Is this correct?

Yep, as others told you.

It might be worth pointing out, though, that Ruby might have a different
idea of falsehood compared to other languages you might be used to:

irb(main):001:0> puts “hey” if 0
hey
=> nil
irb(main):002:0> puts “hey” if []
hey
=> nil

In Python 0 and [] would both evaluate to False.