22
array.include? 'foo' or array.include? 'bar'

is a syntax error (unexpected keyword_or). Parentheses solve the problem, but as I'm new to Ruby I've no idea which of the following is considered more idiomatic:

Option 1

array.include?('foo') or array.include?('bar')

Option 2

(array.include? 'foo') or (array.include? 'bar')

Does this come down to personal preference, or is one approach considered more "correct"?

davidchambers
  • 23,918
  • 16
  • 76
  • 105
  • 2
    It's mostly personal preference. – Adam Eberlin Oct 10 '11 at 01:18
  • 1
    Closely related question: http://stackoverflow.com/questions/7457347/what-is-the-dominant-style-for-parenthesization-of-ruby-function-calls – Andrew Grimm Oct 10 '11 at 01:41
  • second one looks like lisp – anna328p Feb 06 '17 at 03:54
  • We should call more attention to this answer: https://stackoverflow.com/a/7707910/1261335 . In particular, it is important to note that `and` and `or` in Ruby are designed as _control flow_ statements. Their low precedence makes them ideal for that and generally inappropriate for boolean logic. This is tangential to the parentheses problem, but since the question asks about the idiomatic way, the _Ruby idiomatic_ way to write this doesn't involve `or` at all; it should use `||` for boolean logic. – GrandOpener Mar 22 '19 at 20:43

4 Answers4

27

I'd suggest you take a look at the community-driven Ruby coding style guide, here particularly the section on Syntax.

Omit parentheses around parameters for methods that are part of an internal DSL (e.g. Rake, Rails, RSpec), methods that are with "keyword" status in Ruby (e.g. attr_reader, puts) and attribute access methods. Use parentheses around the arguments of all other method invocations. - excerpt from the guide

class Person
  attr_reader :name, :age

  # omitted
end

temperance = Person.new('Temperance', 30)
temperance.name

puts temperance.age

x = Math.sin(y)
array.delete(e)
halloleo
  • 9,216
  • 13
  • 64
  • 122
Bozhidar Batsov
  • 55,802
  • 13
  • 100
  • 117
  • This answer could use an update. The current listing on ruby-style-guide is more informative. ```# bad validates(:name, presence: true) # good validates :name, presence: true ``` – tgf Mar 09 '18 at 23:30
4

Are you sure that is failing? Your initial example works fine for me.

ruby-1.9.2-p290 :002 > array = ['bar']
 => ["bar"] 
ruby-1.9.2-p290 :003 > array.include? 'foo' or array.include? 'bar'
 => true

As a matter of fact, if anything could be considered idiomatic it would be that one. The low precedence of or allows this to work when you leave the parens off. This characteristic is something that should make it idiomatic to Ruby (and even Perl, which or is a hold over from).

Option 1 is super clear, but considering you included the parens you really have no need to use or. It's probably better to use ||, which has a high precedence like other operators and is just more common. I think using or for the sake of it looking like english is not a great practice. It has a semantic meaning within the language and is probably best used for those qualities.

Option 2 is silly of course. If you're going to include parens, you might as well use them for the method signature.

Hope this helps.

Blake Taylor
  • 9,217
  • 5
  • 38
  • 41
  • 2
    `result = array.include? 'foo' or array.include? 'bar'` doesn't work, so your approach doesn't help much. You'd have to add some parentheses somewhere. – Andrew Grimm Oct 10 '11 at 02:09
  • 3
    There's that operator precedence biting people in the ass again. You see, `=` has higher precedence then `or`, so when you say that you're saying `(result = array.include? 'foo') or array.include? 'bar'`. This of course is going to fail. Conditionals will work fine, (i.e. `if ...; ... end`), and if you wrap the entire expression in parens that will work too. This is the kinda thing `or` is *for*, but it's perfectly fine to avoid it. I almost never use. In the end, BDD, and proving your code works, pays off. This frees you to play with your implementation, and that's the real fun of Ruby. – Blake Taylor Oct 10 '11 at 03:16
  • Andrew: That was exactly my problem. Blake: Thanks for the explanation. I think it'll take some time for me to truly understand what's going on here. Hopefully I'll look back at this thread in six months' time and it all makes sense. :) – davidchambers Oct 10 '11 at 05:31
  • Just of note, there is an error in my last comment. This is not how ruby interprets the statement, that would actually work... Anyway, there's a great right up on the use of `and` and `or` here. http://avdi.org/devblog/2010/08/02/using-and-and-or-in-ruby/ Sorry for any confusion. – Blake Taylor Oct 10 '11 at 18:38
4

Avdi Grimm reckons you shouldn't use and or or for boolean logic. You should only and or or for control flow (analogous to if or unless)

According to his recommendation, you should use || instead:

array.include?('foo') || array.include?('bar')
Andrew Grimm
  • 78,473
  • 57
  • 200
  • 338
  • You could say your example as, "if array includes 'foo', or if array includes 'bar'". "or" is okay in this case. You would use the `||` operator if you wanted to say, for example, "if array equals 'foo' or 'bar'": `if array == 'foo' || 'bar'`. In this case, if you replaced `||` with `or`, it would always pass, because you would be saying "if array is 'foo', or if 'bar' returns true.". You can sort of think of it as, `||` is used within the assumed parentheses, and `or` is outside: `if (array == 'foo' || 'bar')` vs. `if (array == 'foo') or 'bar'`. I hope this clears it up a little more. – bricker Oct 10 '11 at 02:21
2

Option 1 is preferred since it's common to other languages as well. Option 2 looks like LISP, which is not popular nowadays.

Candide
  • 30,469
  • 8
  • 53
  • 60
  • 2
    Sadly, you're right about lisp--by far the most productive language I've ever used. Too bad the younger programmers are afraid of it (or worse: don't even know about it). – SMBiggs Apr 27 '14 at 04:52
  • Lisp would have an `or` at the front :) – Rob Grant Oct 08 '14 at 13:25