What's the precedence of ruby's method call

江枫思渺然 提交于 2019-11-26 17:17:03

问题


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!


回答1:


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.




回答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.




回答3:


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




回答4:


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


来源:https://stackoverflow.com/questions/7722369/whats-the-precedence-of-rubys-method-call

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