使用括号和不使用括号的方法调用的优先级是什么?

时间:2022-11-01 23:38:40

Previous answers

The answer to a similar question is wrong.

类似问题的答案是错误的。

Method calls are mentionned neither in Ruby documentation nor in the community wiki.

在Ruby文档和社区维基中都没有提到方法调用。

Method call without parentheses

Higher than or

or seems to have a lower precedence than a method call without parentheses :

或者似乎比没有括号的方法调用具有更低的优先级:

puts false or true

is equivalent to

相当于

( puts false ) or true

and displays false.

并显示错误。

NOTE: I know or shouldn't be used. Still, it's a good example to show that some operators do have lower precedence than method calls.

注意:我知道或不应该使用。不过,这是一个很好的例子,表明某些运算符的优先级低于方法调用。

Lower than ||

puts false || true

is equivalent to

相当于

puts (false || true)

and displays true.

并显示真实。

Method call with parentheses

The parentheses used for method call don't seem to be grouping :

用于方法调用的括号似乎不是分组:

puts(false or true)
# SyntaxError: unexpected keyword_or
puts((false or true))
#=> true

Question

Where should method calls with and without parentheses be in this precedence table?

带括号和不带括号的方法调用应该放在这个优先级表中的哪个位置?

Bounty clarification

I'm looking for the exact location of method calls in the table. Preferably with examples proving it's lower than the previous one and higher than the next one.

我正在寻找表中方法调用的确切位置。优选地,通过示例证明它低于前一个并且高于下一个。

The current answers also don't seem to mention method calls with parentheses.

目前的答案似乎也没有提到带括号的方法调用。

Thanks in advance!

提前致谢!

3 个解决方案

#1


6  

Prelude

This aims to test all possible scenarios.

这旨在测试所有可能的情况。

Note that when saying "operator X has higher precedence than method invocation" what is meant is in arguments. Aka:

注意,当说“运算符X具有比方法调用更高的优先级”时,意味着在参数中。又名:

invocation foo X bar

as opposed to (call on object)

而不是(呼吁对象)

X invocation

As far as the second case is concerned, method calls always have higher precedence.

就第二种情况而言,方法调用始终具有更高的优先级。


Short answer

It doesn't fit:

它不适合:

  • It causes SyntaxError in some cases
  • 在某些情况下会导致SyntaxError

  • It has higher precedence than rescue, but lower than assignment
  • 它具有比救援更高的优先级,但低于分配


Summary

  • not can't be used after method invocation regardless of brackets
  • 无论括号如何,都不能在方法调用后使用

  • Using brackets (()) with method invocations sometimes causes a SyntaxError. These cases are: and, or, if, unless, until, while and rescue
  • 在方法调用中使用方括号(())有时会导致语法错误。这些案件是:和,或者,如果,除非,直到,同时和救援

  • In cases when brackets don't cause an error, they don't change the precedence in any way
  • 如果括号不会导致错误,则它们不会以任何方式更改优先级

  • All operators, except for and, or, postfix if, unless, until, while, rescue have higher precedence than method invocation
  • 所有运算符,除了和,或后缀if,除非,直到,while,具有比方法调用更高的优先级


Lets try it:

让我们尝试一下:

class Noone < BasicObject
  undef_method :!

  def initialize(order)
    @order = order
  end

  def method_missing(name, *args)
    @order << name
    self
  end
end

First unary:

# + and - will become binary
unary_operators = %i(! ~ not defined?)

puts 'No brackets'
unary_operators.each do |operator|
  puts operator

  order = []
  foo = Noone.new order
  bar = Noone.new order
  begin
    eval("foo.meta #{operator} bar")
  rescue SyntaxError => e
    puts e
  end
  p order
  puts '-----------'
end

puts 'Brackets'
unary_operators.each do |operator|
  puts operator

  order = []
  foo = Noone.new order
  bar = Noone.new order
  begin
    eval("foo.meta(#{operator} bar)")
  rescue SyntaxError => e
    puts e
  end
  p order
  puts '-----------'
end

Points taken:

  • not after a method invocation is a SyntaxError
  • 不是在方法调用之后是SyntaxError

  • all unary operators have higher precedence than method invocation regardless of brackets
  • 无论括号如何,所有一元运算符的优先级都高于方法调用


Now binary:

binary_operators = %i(
  **
  * / %
  + -
  << >>
  &
  | ^
  > >= < <=
  <=> == === =~
  .. ...
  or and
)

puts 'No brackets'
binary_operators.each do |operator|
  order = []
  foo = Noone.new order
  bar = Noone.new order
  baz = Noone.new order
  begin
    eval("foo.meta bar #{operator} baz")
  rescue SyntaxError => e
    puts e
  end
  p order
end

puts 'Brackets'
binary_operators.each do |operator|
  order = []
  foo = Noone.new order
  bar = Noone.new order
  baz = Noone.new order
  begin
    eval("foo.meta( bar #{operator} baz)")
  rescue SyntaxError => e
    puts e
  end
  p order
end

Points taken:

  • brackets around method invocation with and or or is a SyntaxError
  • 方法调用周围的括号使用和或或是一个SyntaxError

  • we have to test and and or further without brackets
  • 我们必须测试和/或进一步没有括号

  • .. and ... call <=>. We have to test this further
  • ..和...打电话<=>。我们必须进一步测试

  • we couldn't test a few other binary operators this way, namely &&, ||, ==, !=, modifier rescue, if, unless, until, while
  • 我们无法用这种方式测试其他一些二元运算符,即&&,||,==,!=,modifier rescue,if,除非,直到,而

  • other than the above mentioned, operators have higher precedence, regardless of brackets
  • 除了上面提到的,运营商具有更高的优先权,无论括号如何


def yes
  puts 'yes'
  true
end

def no
  puts 'no'
  false
end

def anything(arg)
  puts 'Anything'
  arg
end

anything yes and no
anything no or yes
anything yes && no
anything no || yes
anything(yes && no)
anything(no || yes)

anything yes == no
anything(yes == no)
anything yes != no
anything(yes != no)

Points taken:

  • and and or have lower precedence without brackets
  • 和和或没有括号的优先级较低

  • &&, ||, == and != have higher precedence regardless of brackets
  • &&,||,==和!=无论括号如何都具有更高的优先级


def five(*args)
  p args
  5
end

five 2..7
five(2..7)
five 2...7
five(2...7)

Points taken:

  • .. and ... have higher precedence regardless of brackets
  • ..和......无论括号如何都有更高的优先级


anything yes if no
anything(yes if no)
anything no unless yes
anything(no unless yes)

anything no until yes
anything(no until yes)
anything yes while no
anything(yes while no)

Points taken:

  • brackets with if, unless, until, while cause a SyntaxError
  • 括号if,除非,until,while导致SyntaxError

  • all of the above have lower precedence than method invocation without brackets
  • 所有上面的优先级都低于没有括号的方法调用


def error
  puts 'Error'
  raise
end

anything error rescue yes
anything(error rescue yes)

Points taken:

  • brackets around rescue cause a SyntaxError
  • 救援周围的括号导致SyntaxError

  • rescue has lower precedence if no brackets are present
  • 如果不存在括号,则救援优先级较低


Ternary:

anything yes ? no : 42
anything(yes ? no : 42)

Points taken:

  • ternary has higher precedence regardless of brackets
  • 无论括号如何,三元都有更高的优先级


Assignment (left for last as it changes yes and no):

分配(留为最后,因为它改变是和否):

anything yes = no
anything(no = five(42))

Points taken:

  • Assignment has higher precedence than invocation
  • 赋值具有比调用更高的优先级

Note that += and the like are just shortcuts for + and = so they exhibit the same behaviour.

请注意,+ =等只是+和=的快捷方式,因此它们表现出相同的行为。

#2


2  

In Ruby, method call precedence seems to be lower than defined? but higher than or.

在Ruby中,方法调用优先级似乎低于定义的?但高于或。

For example:

puts defined? true
#=> true

puts false or true
#=> prints `false` and returns `true`

Note: puts(not true) and puts(false or true) raise syntax errors.

注意:puts(不是true)和puts(false或true)会引发语法错误。

#3


2  

Updating to actually answer the question.

更新以实际回答问题。

Officially methods don't have a precedence. However as you demonstrate we can sort them into the precedence list and they fall between what we could consider "operators" and what we could consider "control flow" keywords.

官方方法没有优先权。然而,正如您所展示的那样,我们可以将它们排序到优先级列表中,它们介于我们可以考虑的“运算符”和我们可以考虑的“控制流”关键字之间。

See, https://ruby-doc.org/core-2.2.0/doc/syntax/precedence_rdoc.html

Which starts with operators, and ends with control-flow constructs like

它从运算符开始,以控制流结构为结束

?, :
modifier-rescue
=, +=, -=, etc.
defined?
not
or, and
modifier-if, modifier-unless, modifier-while, modifier-until

The only oddball there is defined? of which I don't understand why it hasn't been defined as a global function on the Kernel module anyway.

那个唯一的古怪定义了吗?其中我不明白为什么它还没有被定义为内核模块的全局函数。

Missing raise, loop, catch/throw and others?

缺少加注,循环,捕获/抛出等等?

They are not keywords but method calls that are defined as module_function on the Kernel module. And since this module is included in Object they are made into private methods of all classes and thus appear to be global functions that are available everywhere.

它们不是关键字,而是在内核模块上定义为module_function的方法调用。由于这个模块包含在Object中,因此它们被制作成所有类的私有方法,因此看起来是遍布各处的全局函数。

Hope that helps to answer the question. Sorry for the original copypasta.

希望有助于回答这个问题。抱歉原始的copypasta。

#1


6  

Prelude

This aims to test all possible scenarios.

这旨在测试所有可能的情况。

Note that when saying "operator X has higher precedence than method invocation" what is meant is in arguments. Aka:

注意,当说“运算符X具有比方法调用更高的优先级”时,意味着在参数中。又名:

invocation foo X bar

as opposed to (call on object)

而不是(呼吁对象)

X invocation

As far as the second case is concerned, method calls always have higher precedence.

就第二种情况而言,方法调用始终具有更高的优先级。


Short answer

It doesn't fit:

它不适合:

  • It causes SyntaxError in some cases
  • 在某些情况下会导致SyntaxError

  • It has higher precedence than rescue, but lower than assignment
  • 它具有比救援更高的优先级,但低于分配


Summary

  • not can't be used after method invocation regardless of brackets
  • 无论括号如何,都不能在方法调用后使用

  • Using brackets (()) with method invocations sometimes causes a SyntaxError. These cases are: and, or, if, unless, until, while and rescue
  • 在方法调用中使用方括号(())有时会导致语法错误。这些案件是:和,或者,如果,除非,直到,同时和救援

  • In cases when brackets don't cause an error, they don't change the precedence in any way
  • 如果括号不会导致错误,则它们不会以任何方式更改优先级

  • All operators, except for and, or, postfix if, unless, until, while, rescue have higher precedence than method invocation
  • 所有运算符,除了和,或后缀if,除非,直到,while,具有比方法调用更高的优先级


Lets try it:

让我们尝试一下:

class Noone < BasicObject
  undef_method :!

  def initialize(order)
    @order = order
  end

  def method_missing(name, *args)
    @order << name
    self
  end
end

First unary:

# + and - will become binary
unary_operators = %i(! ~ not defined?)

puts 'No brackets'
unary_operators.each do |operator|
  puts operator

  order = []
  foo = Noone.new order
  bar = Noone.new order
  begin
    eval("foo.meta #{operator} bar")
  rescue SyntaxError => e
    puts e
  end
  p order
  puts '-----------'
end

puts 'Brackets'
unary_operators.each do |operator|
  puts operator

  order = []
  foo = Noone.new order
  bar = Noone.new order
  begin
    eval("foo.meta(#{operator} bar)")
  rescue SyntaxError => e
    puts e
  end
  p order
  puts '-----------'
end

Points taken:

  • not after a method invocation is a SyntaxError
  • 不是在方法调用之后是SyntaxError

  • all unary operators have higher precedence than method invocation regardless of brackets
  • 无论括号如何,所有一元运算符的优先级都高于方法调用


Now binary:

binary_operators = %i(
  **
  * / %
  + -
  << >>
  &
  | ^
  > >= < <=
  <=> == === =~
  .. ...
  or and
)

puts 'No brackets'
binary_operators.each do |operator|
  order = []
  foo = Noone.new order
  bar = Noone.new order
  baz = Noone.new order
  begin
    eval("foo.meta bar #{operator} baz")
  rescue SyntaxError => e
    puts e
  end
  p order
end

puts 'Brackets'
binary_operators.each do |operator|
  order = []
  foo = Noone.new order
  bar = Noone.new order
  baz = Noone.new order
  begin
    eval("foo.meta( bar #{operator} baz)")
  rescue SyntaxError => e
    puts e
  end
  p order
end

Points taken:

  • brackets around method invocation with and or or is a SyntaxError
  • 方法调用周围的括号使用和或或是一个SyntaxError

  • we have to test and and or further without brackets
  • 我们必须测试和/或进一步没有括号

  • .. and ... call <=>. We have to test this further
  • ..和...打电话<=>。我们必须进一步测试

  • we couldn't test a few other binary operators this way, namely &&, ||, ==, !=, modifier rescue, if, unless, until, while
  • 我们无法用这种方式测试其他一些二元运算符,即&&,||,==,!=,modifier rescue,if,除非,直到,而

  • other than the above mentioned, operators have higher precedence, regardless of brackets
  • 除了上面提到的,运营商具有更高的优先权,无论括号如何


def yes
  puts 'yes'
  true
end

def no
  puts 'no'
  false
end

def anything(arg)
  puts 'Anything'
  arg
end

anything yes and no
anything no or yes
anything yes && no
anything no || yes
anything(yes && no)
anything(no || yes)

anything yes == no
anything(yes == no)
anything yes != no
anything(yes != no)

Points taken:

  • and and or have lower precedence without brackets
  • 和和或没有括号的优先级较低

  • &&, ||, == and != have higher precedence regardless of brackets
  • &&,||,==和!=无论括号如何都具有更高的优先级


def five(*args)
  p args
  5
end

five 2..7
five(2..7)
five 2...7
five(2...7)

Points taken:

  • .. and ... have higher precedence regardless of brackets
  • ..和......无论括号如何都有更高的优先级


anything yes if no
anything(yes if no)
anything no unless yes
anything(no unless yes)

anything no until yes
anything(no until yes)
anything yes while no
anything(yes while no)

Points taken:

  • brackets with if, unless, until, while cause a SyntaxError
  • 括号if,除非,until,while导致SyntaxError

  • all of the above have lower precedence than method invocation without brackets
  • 所有上面的优先级都低于没有括号的方法调用


def error
  puts 'Error'
  raise
end

anything error rescue yes
anything(error rescue yes)

Points taken:

  • brackets around rescue cause a SyntaxError
  • 救援周围的括号导致SyntaxError

  • rescue has lower precedence if no brackets are present
  • 如果不存在括号,则救援优先级较低


Ternary:

anything yes ? no : 42
anything(yes ? no : 42)

Points taken:

  • ternary has higher precedence regardless of brackets
  • 无论括号如何,三元都有更高的优先级


Assignment (left for last as it changes yes and no):

分配(留为最后,因为它改变是和否):

anything yes = no
anything(no = five(42))

Points taken:

  • Assignment has higher precedence than invocation
  • 赋值具有比调用更高的优先级

Note that += and the like are just shortcuts for + and = so they exhibit the same behaviour.

请注意,+ =等只是+和=的快捷方式,因此它们表现出相同的行为。

#2


2  

In Ruby, method call precedence seems to be lower than defined? but higher than or.

在Ruby中,方法调用优先级似乎低于定义的?但高于或。

For example:

puts defined? true
#=> true

puts false or true
#=> prints `false` and returns `true`

Note: puts(not true) and puts(false or true) raise syntax errors.

注意:puts(不是true)和puts(false或true)会引发语法错误。

#3


2  

Updating to actually answer the question.

更新以实际回答问题。

Officially methods don't have a precedence. However as you demonstrate we can sort them into the precedence list and they fall between what we could consider "operators" and what we could consider "control flow" keywords.

官方方法没有优先权。然而,正如您所展示的那样,我们可以将它们排序到优先级列表中,它们介于我们可以考虑的“运算符”和我们可以考虑的“控制流”关键字之间。

See, https://ruby-doc.org/core-2.2.0/doc/syntax/precedence_rdoc.html

Which starts with operators, and ends with control-flow constructs like

它从运算符开始,以控制流结构为结束

?, :
modifier-rescue
=, +=, -=, etc.
defined?
not
or, and
modifier-if, modifier-unless, modifier-while, modifier-until

The only oddball there is defined? of which I don't understand why it hasn't been defined as a global function on the Kernel module anyway.

那个唯一的古怪定义了吗?其中我不明白为什么它还没有被定义为内核模块的全局函数。

Missing raise, loop, catch/throw and others?

缺少加注,循环,捕获/抛出等等?

They are not keywords but method calls that are defined as module_function on the Kernel module. And since this module is included in Object they are made into private methods of all classes and thus appear to be global functions that are available everywhere.

它们不是关键字,而是在内核模块上定义为module_function的方法调用。由于这个模块包含在Object中,因此它们被制作成所有类的私有方法,因此看起来是遍布各处的全局函数。

Hope that helps to answer the question. Sorry for the original copypasta.

希望有助于回答这个问题。抱歉原始的copypasta。