What's the precedence of ruby's method call

爷,独闯天下 提交于 2019-11-27 15:51:06

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.

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.

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

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
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!