# "if x == x = 1 || x = 2 || x = 3" WTF?!

New post (finally!) on Attack of the Codosaurus, about what happens
when you do some very strange Ruby code:

···

--
Dave Aronson, consulting software developer of Codosaur.us,
PullRequestRoulette.com, Blog.Codosaur.us, and Dare2XL.com.

I think you can write "if x == x = 1" instead of "if x == x = 1 || x = 2 ||
x = 3"
It should be the same thing, am I right?

Well the x = 3 won't be called anyway.

Terry Raimondo

···

On Nov 10, 2016 22:43, "Dave Aronson" <ruby-talk.list.2.TRex@codosaur.us> wrote:

New post (finally!) on Attack of the Codosaurus, about what happens
when you do some very strange Ruby code:
http://blog.codosaur.us/2016/11/x-x-wtf.html

--
Dave Aronson, consulting software developer of Codosaur.us,
PullRequestRoulette.com, Blog.Codosaur.us, and Dare2XL.com.

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk>

Correct. The "x = 1" would return a truthy value and therefore
short-circuit the rest of the boolean expression. That's one reason
why I omitted the rest of it in the investigation. You can
demonstrate this by assigning x 1 and then doing "if x == x = 1 || x =
y || x = z" (being careful not to assign y or z any values
beforehand). You'll get back true, and y and z will still be
undefined.

-Dave

···

On Fri, Nov 11, 2016 at 6:10 AM, Terry Raimondo <terry.raimondo@gmail.com> wrote:

I think you can write "if x == x = 1" instead of "if x == x = 1 || x = 2 ||
x = 3"
It should be the same thing, am I right?

--
Dave Aronson, consulting software developer of Codosaur.us,
PullRequestRoulette.com, Blog.Codosaur.us, and Dare2XL.com.

Definitely!

x will be 1 anyway
Look:

irb(main):052:0* x=3
=> 3
irb(main):053:0> if x == x = 1 || x = 2 || x = 3; puts "True #{x}" ; else ;
puts "False #{x}"; end;
irb(main):054:0* x
False 1
=> 1
irb(main):055:0>

···

2016-11-11 14:10 GMT+03:00 Terry Raimondo <terry.raimondo@gmail.com>:

I think you can write "if x == x = 1" instead of "if x == x = 1 || x = 2
>> x = 3"
It should be the same thing, am I right?

Well the x = 3 won't be called anyway.

Terry Raimondo

On Nov 10, 2016 22:43, "Dave Aronson" <ruby-talk.list.2.TRex@codosaur.us> > wrote:

New post (finally!) on Attack of the Codosaurus, about what happens
when you do some very strange Ruby code:
http://blog.codosaur.us/2016/11/x-x-wtf.html

--
Dave Aronson, consulting software developer of Codosaur.us,
PullRequestRoulette.com, Blog.Codosaur.us, and Dare2XL.com.

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk>

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk>

--
Sincerely Yours

Aleksei Ivanishchev

That's a bad way of testing it, as 'x = y' would leave 'y' undefined
anyway. (I mean, you'd know it wasn't evaluated because there's no
"missing function" exception.)

According to the operator precedence table
http://ruby-doc.org/core-2.3.1/doc/syntax/precedence_rdoc.html the
weird line looks like:

if (x) == ((x = 1) || (x = 2) || (x = 3))

...which short-circuits as you say. (So it's silly.) Note, however,
that the OP paraphrased a line of code he didn't understand. Who knows
what the original author of the code actually wrote, or meant?

···

On 12/11/2016, Dave Aronson <ruby-talk.list.2.TRex@codosaur.us> wrote:

On Fri, Nov 11, 2016 at 6:10 AM, Terry Raimondo > <terry.raimondo@gmail.com> wrote:

I think you can write "if x == x = 1" instead of "if x == x = 1 || x = 2
>>
x = 3"
It should be the same thing, am I right?

Correct. The "x = 1" would return a truthy value and therefore
short-circuit the rest of the boolean expression. That's one reason
why I omitted the rest of it in the investigation. You can
demonstrate this by assigning x 1 and then doing "if x == x = 1 || x =
y || x = z" (being careful not to assign y or z any values
beforehand). You'll get back true, and y and z will still be
undefined.

-Dave

--
Matthew Kerwin
http://matthew.kerwin.net.au/

Slightly off topic: does anyone else shy away from the following as potentially very confusing?

if x = foo()
bar(x)
...

I mean, you have to be looking quite hard indeed to tell it apart from:

if x == foo()
bar(y)
...

...which is a completely different thing. Altogether.

That's a bad way of testing it, as 'x = y' would leave 'y' undefined
anyway. (I mean, you'd know it wasn't evaluated because there's no
"missing function" exception.)

Good point. I was agreeing with the right result, but suggesting the
wrong evidence.

According to the operator precedence table
http://ruby-doc.org/core-2.3.1/doc/syntax/precedence_rdoc.html the
weird line looks like:

if (x) == ((x = 1) || (x = 2) || (x = 3))

...which short-circuits as you say. (So it's silly.)

Yes. That's what led me to investigate it. I know the author and his
code is not usually silly.

Note, however,
that the OP paraphrased a line of code he didn't understand. Who knows
what the original author of the code actually wrote, or meant?

I am the OP, asked the author what he was thinking, and have received
a message in reply that doesn't contradict, and seems to support, that
he meant "is the status one of these three constants" (three
comparisons or'ed together and no assignments). I've since replaced
it with Array#include. (In the real code, the three constants were
not contiguous so I couldn't use a range. Also, even if they happened
to be contiguous now, they were in an Enum so I shouldn't count on
them continuing to be contiguous.)

···

On Fri, Nov 11, 2016 at 5:15 PM, Matthew Kerwin <matthew@kerwin.net.au> wrote:

--
Dave Aronson, consulting software developer of Codosaur.us,
PullRequestRoulette.com, Blog.Codosaur.us, and Dare2XL.com.