# Operator prescedence weirdness

**URL:** <https://rubytalk.org/t/operator-prescedence-weirdness/73263>\
**Category:** ruby-talk\
**Created:** [9 October 2015 18:27 UTC](https://rubytalk.org/t/operator-prescedence-weirdness/73263 "2015-10-09T18:27:14Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Peter\_Hicks](https://avatars.discourse-cdn.com/v4/letter/p/4da419/32.png) [@Peter\_Hicks](https://rubytalk.org/u/Peter_Hicks)\
**Post date:** [9 October 2015 18:27 UTC](https://rubytalk.org/t/operator-prescedence-weirdness/73263/1 "2015-10-09T18:27:14Z")

</div>

All,

Can anyone point me in the direction of what I'm missing here? I'd expect  
the 5th, 6th and 7th commands to all return 'true':

2.2.1 :001 \> a = {}  
=\> {}  
2.2.1 :002 \> a[:foo] = :bar  
=\> :bar  
2.2.1 :003 \> a.has\_key? :foo  
=\> true  
2.2.1 :004 \> a[:foo]  
=\> :bar  
2.2.1 :005 \> a.has\_key? :foo && a[:foo] == :bar  
=\> false  
2.2.1 :006 \> a.has\_key? :foo && (a[:foo] == :bar)  
=\> false  
2.2.1 :007 \> (a.has\_key? :foo) && a[:foo] == :bar  
=\> true

I realise I can just do a[:foo] == bar, as a[:foo] will return nil if  
there's no :foo member.

Peter

---

<div class="post-metadata">

**Author:** ![Dave\_Aronson](https://avatars.discourse-cdn.com/v4/letter/d/7ba0ec/32.png) [@Dave\_Aronson](https://rubytalk.org/u/Dave_Aronson)\
**Post date:** [9 October 2015 18:32 UTC](https://rubytalk.org/t/operator-prescedence-weirdness/73263/2 "2015-10-09T18:32:33Z")

</div>

> Can anyone point me in the direction of what I'm missing here? I'd expect  
> the 5th, 6th and 7th commands to all return 'true':

...

> 2.2.1 :005 \> a.has\_key? :foo && a[:foo] == :bar  
> =\> false  
> 2.2.1 :006 \> a.has\_key? :foo && (a[:foo] == :bar)  
> =\> false  
> 2.2.1 :007 \> (a.has\_key? :foo) && a[:foo] == :bar  
> =\> true

This is one of those cases where not using the optional parentheses on  
a method call will bite you. Without even looking up the order of  
precedence, I can tell you that using parens will fix it. Try:

&nbsp;&nbsp;a.has\_key?(:foo) && a[:foo] == :bar

This returns true.

-Dave

> **···**
>
> On Fri, Oct 9, 2015 at 2:27 PM, Peter Hicks \<peter.hicks@poggs.co.uk\> wrote:
> 
> --  
> Dave Aronson, consulting software developer of Codosaur.us,  
> PullRequestRoulette.com, Blog.Codosaur.us, and Dare2XL.com.

---

<div class="post-metadata">

**Author:** ![Joshua\_Bodah](https://avatars.discourse-cdn.com/v4/letter/j/f0a364/32.png) [@Joshua\_Bodah](https://rubytalk.org/u/Joshua_Bodah)\
**Post date:** [9 October 2015 20:14 UTC](https://rubytalk.org/t/operator-prescedence-weirdness/73263/3 "2015-10-09T20:14:14Z")

</div>

The issue is that the right side expression is evaluated first. Ruby parses this and sees has\_key? and some expression. Since there are no parent then it assumes you want to pass the entire expression to has\_key?, so it reduces that expression first before passing it to has\_key?. When you add parents you are being explicit about how expressions should be reduced

Josh

> **···**
>
> Sent from my iPhone
> 
> > On Oct 9, 2015, at 2:27 PM, Peter Hicks \<peter.hicks@poggs.co.uk\> wrote:
> > 
> > All,
> > 
> > Can anyone point me in the direction of what I'm missing here? I'd expect the 5th, 6th and 7th commands to all return 'true':
> > 
> > 2.2.1 :001 \> a = {}  
> > =\> {}  
> > 2.2.1 :002 \> a[:foo] = :bar  
> > =\> :bar  
> > 2.2.1 :003 \> a.has\_key? :foo  
> > =\> true  
> > 2.2.1 :004 \> a[:foo]  
> > =\> :bar  
> > 2.2.1 :005 \> a.has\_key? :foo && a[:foo] == :bar  
> > =\> false  
> > 2.2.1 :006 \> a.has\_key? :foo && (a[:foo] == :bar)  
> > =\> false  
> > 2.2.1 :007 \> (a.has\_key? :foo) && a[:foo] == :bar  
> > =\> true
> > 
> > I realise I can just do a[:foo] == bar, as a[:foo] will return nil if there's no :foo member.
> > 
> > Peter

---

<div class="post-metadata">

**Author:** ![Peter\_Hicks](https://avatars.discourse-cdn.com/v4/letter/p/4da419/32.png) [@Peter\_Hicks](https://rubytalk.org/u/Peter_Hicks)\
**Post date:** [9 October 2015 19:10 UTC](https://rubytalk.org/t/operator-prescedence-weirdness/73263/4 "2015-10-09T19:10:54Z")

</div>

Hi Dave

> **···**
>
> On Fri, 9 Oct 2015 at 19:40 Dave Aronson \<ruby-talk.list.2.TRex@codosaur.us\> wrote:
> 
> > This is one of those cases where not using the optional parentheses on  
> > a method call will bite you. Without even looking up the order of  
> > precedence, I can tell you that using parens will fix it. Try:
> > 
> > &nbsp;&nbsp;a.has\_key?(:foo) && a[:foo] == :bar
> > 
> > This returns true.
> 
> "Optional parentheses" are the two key words here - thanks, I didn't  
> realise they were the problem.
> 
> Peter

---

<div class="post-metadata">

**Author:** ![Matthew\_Kerwin](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/matthew_kerwin/32/1845_2.png) [@Matthew\_Kerwin](https://rubytalk.org/u/Matthew_Kerwin)\
**Post date:** [9 October 2015 21:21 UTC](https://rubytalk.org/t/operator-prescedence-weirdness/73263/5 "2015-10-09T21:21:37Z")

</div>

Or use 'and' instead of '&&'. (I think, I don't have ruby on my phone to  
verify)

> **···**
>
> On 10/10/2015 6:14 AM, \<jb3689@yahoo.com\> wrote:
> 
> > The issue is that the right side expression is evaluated first. Ruby  
> > parses this and sees has\_key? and some expression. Since there are no  
> > parent then it assumes you want to pass the entire expression to has\_key?,  
> > so it reduces that expression first before passing it to has\_key?. When you  
> > add parents you are being explicit about how expressions should be reduced
> > 
> > Josh
> > 
> > Sent from my iPhone
> > 
> > \> On Oct 9, 2015, at 2:27 PM, Peter Hicks \<peter.hicks@poggs.co.uk\> wrote:  
> > \>  
> > \> All,  
> > \>  
> > \> Can anyone point me in the direction of what I'm missing here? I'd  
> > expect the 5th, 6th and 7th commands to all return 'true':  
> > \>  
> > \> 2.2.1 :001 \> a = {}  
> > \> =\> {}  
> > \> 2.2.1 :002 \> a[:foo] = :bar  
> > \> =\> :bar  
> > \> 2.2.1 :003 \> a.has\_key? :foo  
> > \> =\> true  
> > \> 2.2.1 :004 \> a[:foo]  
> > \> =\> :bar  
> > \> 2.2.1 :005 \> a.has\_key? :foo && a[:foo] == :bar  
> > \> =\> false  
> > \> 2.2.1 :006 \> a.has\_key? :foo && (a[:foo] == :bar)  
> > \> =\> false  
> > \> 2.2.1 :007 \> (a.has\_key? :foo) && a[:foo] == :bar  
> > \> =\> true  
> > \>  
> > \> I realise I can just do a[:foo] == bar, as a[:foo] will return nil if  
> > there's no :foo member.  
> > \>  
> > \>  
> > \> Peter

---

<div class="post-metadata">

**Author:** ![Dave\_Aronson](https://avatars.discourse-cdn.com/v4/letter/d/7ba0ec/32.png) [@Dave\_Aronson](https://rubytalk.org/u/Dave_Aronson)\
**Post date:** [9 October 2015 23:48 UTC](https://rubytalk.org/t/operator-prescedence-weirdness/73263/6 "2015-10-09T23:48:42Z")

</div>

> Or use 'and' instead of '&&'.

Aiieeee! No no, 1\_000\_000.times { no! } Please do not resort to such  
horrid kluges as using those \*flow control operators\* when you should  
be using a \*boolean operator\*!

Better yet, just forget the verbal versions even exist. Unless you're  
coming from Perl, they are unnatural and misleading. See  
[Ruby Gotchas - Google Slides](http://bit.ly/RubyGotchas) (the slides from my Ruby Gotchas  
presentation) for details, the slides titled "and != &&" and "or !=

> > ".

-Dave

> **···**
>
> On Fri, Oct 9, 2015 at 5:21 PM, Matthew Kerwin \<matthew@kerwin.net.au\> wrote:
> 
> --  
> Dave Aronson, consulting software developer of Codosaur.us,  
> PullRequestRoulette.com, Blog.Codosaur.us, and Dare2XL.com.

---

<div class="post-metadata">

**Author:** ![Robert\_K1](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/robert_k1/32/1830_2.png) [@Robert\_K1](https://rubytalk.org/u/Robert_K1)\
**Post date:** [11 October 2015 18:07 UTC](https://rubytalk.org/t/operator-prescedence-weirdness/73263/7 "2015-10-11T18:07:13Z")

</div>

> \> Or use 'and' instead of '&&'.
> 
> Aiieeee! No no, 1\_000\_000.times { no! } Please do not resort to such  
> horrid kluges as using those \*flow control operators\* when you should  
> be using a \*boolean operator\*!

"and" is the same boolean operator as "&&" with the same semantics with  
regard to short circuiting (which makes both useful for flow control). The  
only difference is precedence which is much lower in case of "and". Why are  
you making this distinction between "boolean operators" and "flow control  
operators"?

> Better yet, just forget the verbal versions even exist. Unless you're  
> coming from Perl, they are unnatural and misleading.

Every language has its idioms. That "and" and "or" are "banned" (see [1])  
is completely new to me. And I don't see an issue with using them. They are  
handy for exactly these kinds of situations and where you want to make code  
human readable. Of course you need to be aware of their properties - but  
that is true for all the other language constructs as well.

> See  
> [Ruby Gotchas - Google Slides](http://bit.ly/RubyGotchas) (the slides from my Ruby Gotchas  
> presentation) for details, the slides titled "and != &&" and "or !=  
> \>\>".

What style guide are you referring to? I would like to hear some more  
reasoning. The style guide I found [1] just states not to do it but does  
not give a reason as far as I can see.

Kind regards

robert

[1] [GitHub - rubocop/ruby-style-guide: A community-driven Ruby coding style guide](https://github.com/bbatsov/ruby-style-guide#no-and-or-or)

> **···**
>
> On Sat, Oct 10, 2015 at 1:48 AM, Dave Aronson \< ruby-talk.list.2.TRex@codosaur.us\> wrote:
> 
> > On Fri, Oct 9, 2015 at 5:21 PM, Matthew Kerwin \<matthew@kerwin.net.au\> \> wrote:
> 
> --  
> [guy, jim, charlie].each {|him| remember.him do |as, often| as.you\_can -  
> without end}  
> [http://blog.rubybestpractices.com/](http://blog.rubybestpractices.com/)

---

<div class="post-metadata">

**Author:** ![Dave\_Aronson](https://avatars.discourse-cdn.com/v4/letter/d/7ba0ec/32.png) [@Dave\_Aronson](https://rubytalk.org/u/Dave_Aronson)\
**Post date:** [11 October 2015 18:45 UTC](https://rubytalk.org/t/operator-prescedence-weirdness/73263/8 "2015-10-11T18:45:57Z")

</div>

> 

...

> > Please do not resort to such  
> > horrid kluges as using those \*flow control operators\* when you should  
> > be using a \*boolean operator\*!
> 
> "and" is the same boolean operator as "&&" with the same semantics with  
> regard to short circuiting (which makes both useful for flow control). The  
> only difference is precedence which is much lower in case of "and". Why are  
> you making this distinction between "boolean operators" and "flow control  
> operators"?

Precedence makes a huge difference. The lower precedence of "and" and  
"or" makes them horribly misleading in a normal boolean expression  
where you're trying to calculate the resulting truth value. This is a  
violation of one of Ruby's core principles, that of Least  
Astonishment. They are much more commonly used (at least in correct  
code) for flow control, in Perlish idioms such as "do\_this and  
do\_that" (do this, and only if that succeeded, assuming that it  
returns a boolean value to indicate success or failure, proceed to do  
that) and "do\_something or give\_error\_message" (do something, and if  
that fails, making the same assumption, then give an error message).  
Ruby has perfectly good idioms for these situations, that is even  
clearer (no surprise when comparing against Perl): "do\_that if  
do\_this" and "give\_error\_message unless do\_something".

> > Better yet, just forget the verbal versions even exist. Unless you're  
> > coming from Perl, they are unnatural and misleading.
> 
> Every language has its idioms. That "and" and "or" are "banned" (see [1]) is  
> completely new to me. And I don't see an issue with using them. They are  
> handy for exactly these kinds of situations and where you want to make code  
> human readable. Of course you need to be aware of their properties - but  
> that is true for all the other language constructs as well.

But their properties are not at all obvious! They masquerade as the  
normal boolean operators, simply more humanized versions of && and ||,  
while they certainly are not at all equivalent, leading to astonishing  
bugs. It's usually not until one has been sorely bitten by such a  
bug, or see it discussed, that one finds out about this vital  
difference.

> > See [http://bit.ly/RubyGotchas](http://bit.ly/RubyGotchas) (the slides from my  
> > Ruby Gotchas presentation) for details, the slides  
> > titled "and != &&" and "or != ||".
> 
> What style guide are you referring to? I would like to hear some more  
> reasoning. The style guide I found [1] just states not to do it but does not  
> give a reason as far as I can see.

...

> [1] [https://github.com/bbatsov/ruby-style-guide#no-and-or-or](https://github.com/bbatsov/ruby-style-guide#no-and-or-or)

Frankly I now forget which one I had in mind, but it was most likely  
either that one or Github's, which borrows heavily from it. You're  
right that it is light on the reasoning. I believe it's because the  
use of "and" and "or" looks tempting to people (not necessarily even  
just newbies!) trying to make the code more human-readable, but  
introducing subtle bugs that arise from the difference in precedence.  
Both guides say "It's just not worth it"; I believe that what they  
mean is that the slight better readability is not worth the pain of  
creating, encountering, and debugging such bugs... especially when  
these operators just won't do what you probably want (if you're  
looking for a calculation of a boolean value resulting from combining  
several things).

I'll put in a pull request for BBatsov's, providing an example for  
better clarity of the bug-potential, plus offering the above  
Ruby-idiomatic snippets as alternatives.

-Dave

> **···**
>
> On Sun, Oct 11, 2015 at 2:07 PM, Robert Klemme \<shortcutter@googlemail.com\> wrote:
> 
> > On Sat, Oct 10, 2015 at 1:48 AM, Dave Aronson \> \<ruby-talk.list.2.TRex@codosaur.us\> wrote:
> 
> --  
> Dave Aronson, consulting software developer of Codosaur.us,  
> PullRequestRoulette.com, Blog.Codosaur.us, and Dare2XL.com.

---

<div class="post-metadata">

**Author:** ![James\_Pacheco](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/james_pacheco/32/2457_2.png) [@James\_Pacheco](https://rubytalk.org/u/James_Pacheco)\
**Post date:** [11 October 2015 18:28 UTC](https://rubytalk.org/t/operator-prescedence-weirdness/73263/9 "2015-10-11T18:28:57Z")

</div>

From Avdi Grimm:  
[http://devblog.avdi.org/2014/08/26/how-to-use-rubys-english-andor-operators-without-going-nuts/](http://devblog.avdi.org/2014/08/26/how-to-use-rubys-english-andor-operators-without-going-nuts/)

He basically says "they're flow control, not logic". The difference in  
precedence can be confusing or surprising. If someone chooses 'and' because  
it's more readable than '&&', but fails to take into consideration that  
they've change their precedence, it becomes dangerous. In many ways, it's  
easier to just "forget that they exist", since && and || will cover your  
use cases 99% of the time.

-J

> **···**
>
> On Sun, Oct 11, 2015 at 11:08 AM Robert Klemme \<shortcutter@googlemail.com\> wrote:
> 
> > On Sat, Oct 10, 2015 at 1:48 AM, Dave Aronson \< \> ruby-talk.list.2.TRex@codosaur.us\> wrote:
> > 
> > > On Fri, Oct 9, 2015 at 5:21 PM, Matthew Kerwin \<matthew@kerwin.net.au\> \>\> wrote:
> > > 
> > > \> Or use 'and' instead of '&&'.
> > > 
> > > Aiieeee! No no, 1\_000\_000.times { no! } Please do not resort to such  
> > > horrid kluges as using those \*flow control operators\* when you should  
> > > be using a \*boolean operator\*!
> > 
> > "and" is the same boolean operator as "&&" with the same semantics with  
> > regard to short circuiting (which makes both useful for flow control). The  
> > only difference is precedence which is much lower in case of "and". Why are  
> > you making this distinction between "boolean operators" and "flow control  
> > operators"?
> > 
> > > Better yet, just forget the verbal versions even exist. Unless you're  
> > > coming from Perl, they are unnatural and misleading.
> > 
> > Every language has its idioms. That "and" and "or" are "banned" (see [1])  
> > is completely new to me. And I don't see an issue with using them. They are  
> > handy for exactly these kinds of situations and where you want to make code  
> > human readable. Of course you need to be aware of their properties - but  
> > that is true for all the other language constructs as well.
> > 
> > > See  
> > > [http://bit.ly/RubyGotchas](http://bit.ly/RubyGotchas) (the slides from my Ruby Gotchas  
> > > presentation) for details, the slides titled "and != &&" and "or !=  
> > > \>\>".
> > 
> > What style guide are you referring to? I would like to hear some more  
> > reasoning. The style guide I found [1] just states not to do it but does  
> > not give a reason as far as I can see.
> > 
> > Kind regards
> > 
> > robert
> > 
> > [1] [https://github.com/bbatsov/ruby-style-guide#no-and-or-or](https://github.com/bbatsov/ruby-style-guide#no-and-or-or)
> > 
> > --  
> > [guy, jim, charlie].each {|him| remember.him do |as, often| as.you\_can -  
> > without end}  
> > [http://blog.rubybestpractices.com/](http://blog.rubybestpractices.com/)

---

<div class="post-metadata">

**Author:** ![Robert\_K1](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/robert_k1/32/1830_2.png) [@Robert\_K1](https://rubytalk.org/u/Robert_K1)\
**Post date:** [12 October 2015 11:41 UTC](https://rubytalk.org/t/operator-prescedence-weirdness/73263/10 "2015-10-12T11:41:23Z")

</div>

Dave, thank you for going through the effort to share your reasoning!

> \>  
> ...  
> \>\> Please do not resort to such  
> \>\> horrid kluges as using those \*flow control operators\* when you should  
> \>\> be using a \*boolean operator\*!  
> \>  
> \> "and" is the same boolean operator as "&&" with the same semantics with  
> \> regard to short circuiting (which makes both useful for flow control).  
> The  
> \> only difference is precedence which is much lower in case of "and". Why  
> are  
> \> you making this distinction between "boolean operators" and "flow control  
> \> operators"?
> 
> Precedence makes a huge difference. The lower precedence of "and" and  
> "or" makes them horribly misleading in a normal boolean expression  
> where you're trying to calculate the resulting truth value. This is a  
> violation of one of Ruby's core principles, that of Least  
> Astonishment.

People tend to forget that the principle of least surprise applies to Matz.  
This is an important restriction that changes semantics quite a bit. See  
[http://www.artima.com/intv/ruby4.html](http://www.artima.com/intv/ruby4.html)

> They are much more commonly used (at least in correct  
> code) for flow control, in Perlish idioms such as "do\_this and  
> do\_that" (do this, and only if that succeeded, assuming that it  
> returns a boolean value to indicate success or failure, proceed to do  
> that) and "do\_something or give\_error\_message" (do something, and if  
> that fails, making the same assumption, then give an error message).  
> Ruby has perfectly good idioms for these situations, that is even  
> clearer (no surprise when comparing against Perl): "do\_that if  
> do\_this" and "give\_error\_message unless do\_something".

Actually I use both idioms. I would use "if" only if "do\_this" is a test of  
some kind. I would use "and" if "do\_this" was some kind of task that can  
end successfully or not and I want to "do\_that" only if "do\_this" was  
successful.

> \>\> Better yet, just forget the verbal versions even exist. Unless you're  
> \>\> coming from Perl, they are unnatural and misleading.  
> \>  
> \> Every language has its idioms. That "and" and "or" are "banned" (see  
> [1]) is  
> \> completely new to me. And I don't see an issue with using them. They are  
> \> handy for exactly these kinds of situations and where you want to make  
> code  
> \> human readable. Of course you need to be aware of their properties - but  
> \> that is true for all the other language constructs as well.
> 
> But their properties are not at all obvious!

Define "obvious". 🙂 Seriously, all language constructs have properties  
that cannot be seen immediately. We have to learn them. Maybe you mean with  
"obvious" here something like "function the same was as in other languages  
X, Y and Z". But these languages often do not have something like operator  
"and" and people will have to learn this new thing anyway.

> They masquerade as the  
> normal boolean operators, simply more humanized versions of && and ||,  
> while they certainly are not at all equivalent, leading to astonishing  
> bugs. It's usually not until one has been sorely bitten by such a  
> bug, or see it discussed, that one finds out about this vital  
> difference.

I can only speak for me: I learned about the different precedence right  
from the start so to me they never "masqueraded" as anything else.

> \>\> See [http://bit.ly/RubyGotchas](http://bit.ly/RubyGotchas) (the slides from my  
> \>\> Ruby Gotchas presentation) for details, the slides  
> \>\> titled "and != &&" and "or != ||".  
> \>  
> \> What style guide are you referring to? I would like to hear some more  
> \> reasoning. The style guide I found [1] just states not to do it but does  
> not  
> \> give a reason as far as I can see.  
> ...  
> \> [1] [https://github.com/bbatsov/ruby-style-guide#no-and-or-or](https://github.com/bbatsov/ruby-style-guide#no-and-or-or)
> 
> Frankly I now forget which one I had in mind, but it was most likely  
> either that one or Github's, which borrows heavily from it. You're  
> right that it is light on the reasoning. I believe it's because the  
> use of "and" and "or" looks tempting to people (not necessarily even  
> just newbies!) trying to make the code more human-readable, but  
> introducing subtle bugs that arise from the difference in precedence.  
> Both guides say "It's just not worth it"; I believe that what they  
> mean is that the slight better readability is not worth the pain of  
> creating, encountering, and debugging such bugs... especially when  
> these operators just won't do what you probably want (if you're  
> looking for a calculation of a boolean value resulting from combining  
> several things).

I cannot really say how much confusion they create in the community, for me  
that problem does not exist. From my memory (which is feeble) I have seen  
far more threads here about the confusing properties of class variables  
than of "and". 🙂

> I'll put in a pull request for BBatsov's, providing an example for  
> better clarity of the bug-potential, plus offering the above  
> Ruby-idiomatic snippets as alternatives.

It's always good to make reasoning of such rules transparent. You are doing  
the community a good service! Thank you!

Kind regards

robert

> **···**
>
> On Sun, Oct 11, 2015 at 8:45 PM, Dave Aronson \< ruby-talk.list.2.TRex@codosaur.us\> wrote:
> 
> > On Sun, Oct 11, 2015 at 2:07 PM, Robert Klemme \> \<shortcutter@googlemail.com\> wrote:  
> > \> On Sat, Oct 10, 2015 at 1:48 AM, Dave Aronson \> \> \<ruby-talk.list.2.TRex@codosaur.us\> wrote:
> 
> --  
> [guy, jim, charlie].each {|him| remember.him do |as, often| as.you\_can -  
> without end}  
> [http://blog.rubybestpractices.com/](http://blog.rubybestpractices.com/)
