-1

In the code below, if I replace the and in the any? statement with &&, it throws an error unexpected tIDENTIFIER, expecting '}'.

def ArrayAddition(arr)
  i = 2
  until i == arr.length
    combinations = arr.permutation(i).to_a
    return true if combinations.any?{|array| array.inject(&:+) == arr.max and !array.include? arr.max}
    i+=1
  end
    false
end

What is going on here? Does Ruby handle these operators differently?

sawa
  • 165,429
  • 45
  • 277
  • 381
Marc Fletcher
  • 932
  • 1
  • 16
  • 39

2 Answers2

3

Yes. and has lower precedence than && (and almost everything else). This expression:

foo and bar baz

...is parsed like this:

foo and (bar baz)

...so Ruby knows foo is a method name (because it can't be anything else). On the other hand, this expression:

foo && bar baz

...is parsed like this:

(foo && bar) baz

...which just doesn't make sense and you get a syntax error.

Generally speaking you should use && unless you specifically want and's lower precedence, so in this case the easiest fix to the syntax error is to use parentheses around the method argument:

foo && bar(baz)

...and so:

array.inject(&:+) == arr.max && !array.include?(arr.max)

As a bonus, this is more readable as well.

Jordan Running
  • 102,619
  • 17
  • 182
  • 182
3

The operators and and && have different precedence, and are not equivalent. As such, the Ruby Style Guide advises against using and and or operators: The and and or keywords are banned. It's just not worth it. Always use && and || instead.

Due to the difference in precedence, the other operators in the expression have higher or lower comparative precedence. In this case, the argument for the Array#include? call end up binding to the wrong expression.

You can solve this by adding parentheses around the argument to the Array#include? call.

Michael Gaskill
  • 7,913
  • 10
  • 38
  • 43
  • 1
    If you have something constructive to add to the answer, please comment. Arbitrary anonymous downvotes do nothing to improve the quality of the answers. – Michael Gaskill May 20 '16 at 04:59
  • 2
    Upvoted to counteract whatever troll has decided to inflict themselves upon us tonight (I have a guess...), and for the style guide link. – Jordan Running May 20 '16 at 05:07
  • Thanks, @Jordan - I have no idea who it might be. I'd certainly prefer constructive feedback to improve the answer. But I guess it's easier (and maybe more satisfying) to just downvote an answer and move on... – Michael Gaskill May 20 '16 at 05:15
  • 1
    *"Always use && and || instead."* is quite harsh. `and` and `or` work great for control flow. – Stefan May 20 '16 at 06:13