Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Logical OR in Ruby

10 views
Skip to first unread message

Paul Sholtz

unread,
Mar 21, 2011, 12:09:49 AM3/21/11
to
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?

--
Posted via http://www.ruby-forum.com/.

pat eyler

unread,
Mar 21, 2011, 12:14:25 AM3/21/11
to

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>


> --
> Posted via http://www.ruby-forum.com/.
>
>

--
thanks,
-pate
-------------------------
 Don't judge those who choose to sin differently than you do

Michael Edgar

unread,
Mar 21, 2011, 12:36:17 AM3/21/11
to
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 Edgar
ad...@carboni.ca
http://carboni.ca/

Stefano Mioli

unread,
Mar 21, 2011, 11:36:05 AM3/21/11
to
On 21/03/2011 5.09, Paul Sholtz 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.

--
Stefano

Colin Bartlett

unread,
Mar 21, 2011, 11:55:02 AM3/21/11
to
On Mon, Mar 21, 2011 at 4:09 AM, Paul Sholtz <paul....@gmail.com> 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 it’s 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 doesn’t 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.

0 new messages