5

http://phrogz.net/programmingruby/language.html#table_18.4 The table provided by the link above only gives the precedence of ruby's operators. What's the precedence of a method(or should I say: a message/ function) ?

For example, when I input something as below in irb

Math.sqrt 2 + 2

I got 2.0 as the result. Without the definite rules of the precedence, I just can't decide where to use the parens and where to omit them. So, someone please help me get rid of this uncertainty. Thanks in advance!

Need4Steed
  • 2,170
  • 3
  • 22
  • 30

4 Answers4

4

Any operator has precedence over the method call. It is highly recommended to use () for method calls to avoid situations like the one you're asking about.

K M Rakibul Islam
  • 33,760
  • 12
  • 89
  • 110
  • 4
    `Any operator has precedence over the method call`. This is wrong. `puts false or true` displays `false`, `puts false || true` displays `true`. – Eric Duminil Dec 24 '16 at 11:51
  • 1
    In addition to @Eric's observation, what value is an answer that makes an assertion with no evidence? – Cary Swoveland Mar 25 '23 at 02:14
2

We can use your Programming Ruby link as a starting point and discover for ourselves where unparenthesized method-calls belong in the precedence table. I'm only going to show the final tests that pinpoint the location.

It's lower than defined?:

defined? Math.sqrt 2
# => SyntaxError: unexpected tINTEGER, expecting end-of-input

Aha, it's higher than not:

not Math.sqrt 2
=> false

Now you know exactly when you should use parentheses.

Sidenote

(thanks to Martin Demello's link to ruby-talk for reminding me)

Keep in mind that the operators in the table only apply when not being used in the method-call syntax. Example - the following doesn't obey the rules for * and + because they're not being used as operators, but methods:

# This happens because unparenthesized method calls are right-associative.
2.* 5.+ 2  # => 14

If that looks confusing, the same thing is happening here:

# The `modulo` is evaluated first because it's on the right
Math.sqrt 9.modulo 5
Kelvin
  • 20,119
  • 3
  • 60
  • 68
2

Ruby method invocation has a lower precedence than any of the operators, but that's not the full story - there are some edge cases that are nonobvious. Your question got me curious about one of them, so I asked on the ruby-talk mailing list. You should find the resulting thread helpful.

Also, read this blog post for a good argument that you should use parentheses liberally, especially while you are learning ruby.

Martin DeMello
  • 11,876
  • 7
  • 49
  • 64
1

In Ruby any operator has precedence over method calls, e.g. operators are evaluated first.

However the example Math.sqrt 2 + 2 is a good illustration on how hard to read and unintuitive it can be to leave out parentheses. One might expect Math.sqrt(2) + 2 to be evaluated here.

When you come across a line like this, you might think: What did the coder intend? Is this a bug?

It is always a good idea to use parentheses whenever you can, to make clear what you want, especially when there is a method call or multiple operators - it's just good style, and the lowest risk approach (e.g. don't make assumptions, but make yourself clear by using parentheses).

It never hurts to add extra parentheses in expressions, but leaving them out can hurt quite a bit.

Here's a nice example which I recently came across:

  def foo(arg)
    raise "error"
  end
  x = foo 4 rescue 7
  x 
    => nil    # oops!

  x = foo(4) rescue 7
  x
    => 7

I hope this nicely illustrates why it's important to use parentheses

Also:

Check here, under "Calling a Method" : http://ruby-doc.org/docs/ProgrammingRuby/html/tut_methods.html Quote:

[...] If there is no ambiguity you can omit the parentheses around the argument list when calling a method.[...] However, except in the simplest cases we don't recommend this---there are some subtle problems that can trip you up.[In particular, you must use parentheses on a method call that is itself a parameter to another method call (unless it is the last parameter).] Our rule is simple: if there's any doubt, use parentheses.

See also: http://phrogz.net/programmingruby/language.html

Tilo
  • 33,354
  • 5
  • 79
  • 106
  • @Tile, could I get some direct answers, plz? – Need4Steed Oct 11 '11 at 07:00
  • @Need4Steed I think he is right - you should just google it - it doesn't seem like you researched the question yourself at all –  Oct 11 '11 at 07:31
  • I don't see any trolling, and I checked the edits. This answer was helpful. – d11wtq Oct 11 '11 at 09:01
  • 2
    google what exactly? i spent ten to fifteen minutes trying to find a helpful page to point the OP to, and came up blank. and i've been using ruby for the last 12 years, so i had a pretty good idea of what search terms to use. as for tile's answer, it was not only unhelpful (as he'd have seen had he actually bothered to read the original question properly and/or actually run the query), but it linked to lmgtfy, which if not full-fledged trolling is at least gratuitously rude. – Martin DeMello Oct 12 '11 at 09:00
  • @Martin: googling "Ruby Operator Precedence" and "Ruby Method Call parentheses" brought very helpful results for me -- Tilo's answer was pointing in the right direction. LMGTFY is simply pointing out that the answer is easy to find, if one makes an effort. –  Oct 12 '11 at 12:32
  • need4steed's questions was very specific, though - he wanted to know the exact rules that governed the parsing and precedence of ruby method call arguments, and that is indeed pretty hard to find spelt out – Martin DeMello Oct 12 '11 at 15:26
  • why do people got to be such jerks about things? Just because the answer is out there doesn't mean that everyone can read it and understand it on the same level. – killerbarney Feb 28 '13 at 00:56
  • I hope this clarifies the answer – Tilo Mar 07 '13 at 09:15
  • This is actually wrong, `Math.sqrt 2 + 2` is interpreted as `Math.sqrt(2 + 2)`. Also I highly doubt leaving out parenthesis is a result of being “lazy”. You also don’t really answer the question, and instead sidestep it by just saying to always use parenthesis. – Andrew Marshall Jul 15 '13 at 05:08
  • -1 because the Ruby in the middle is inaccurate (EDIT: for 1.9.3, at least). If, like the comment says, `&&` and `||` have the same precedence, I'd expect that first statement to evaluate left-to-right i.e. `(true || true) && false`, which is `false`. Also the second statement states that `true || (true && false)` is `false` when it isn't, it's `true`. – nickgrim Dec 30 '13 at 23:02