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

What's the precedence of method calls with and without parentheses?

以前的答案

answer to a similar question错了

Ruby documentation nor in the community wiki.

中均未提及方法调用

不带括号的方法调用

高于or

or 的优先级似乎低于不带括号的方法调用:

puts false or true

等同于

( puts false ) or true

并显示 false.

注意:我知道不应该使用 or。尽管如此,这仍然是一个很好的例子,表明某些运算符的优先级确实低于方法调用。

低于||

puts false || true

等同于

puts (false || true)

并显示 true.

带括号的方法调用

用于方法调用的括号don't seem要分组:

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

问题

在此优先级中,带括号和不带括号的方法调用应该放在什么位置table

悬赏说明

我正在寻找 table 中方法调用的确切位置。最好有例子证明比上一个低,比下一个高

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

提前致谢!

在Ruby中,方法调用优先级似乎低于defined?但高于or

例如:

puts defined? true
#=> true

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

注意: puts(not true)puts(false or true) 引发语法错误。

正在更新以实际回答问题。

官方方法没有优先级。然而,正如您所展示的,我们可以将它们分类到优先级列表中,它们介于我们可以考虑的 "operators" 和我们可以考虑的 "control flow" 关键字之间。

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

以运算符开始,以控制流结构结束,例如

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

唯一奇怪的是 defined?,我不明白为什么它没有在 Kernel 模块上定义为全局函数。

缺少 raiseloopcatch/throw 和其他人?

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

希望对回答问题有所帮助。原版copypasta抱歉。

序曲

这旨在测试所有可能的场景。

注意 当说 "operator X has higher precedence than method invocation" 时,意思是在参数中。又名:

invocation foo X bar

相对于(调用对象)

X invocation

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


简答

不合适:

  • 在某些情况下会导致SyntaxError
  • 它的优先级高于rescue,但低于赋值

总结

  • not 方法调用后无论括号如何都不能使用
  • 在方法调用中使用方括号 (()) 有时会导致 SyntaxError。这些情况是:andorifunlessuntilwhilerescue
  • 在括号不会导致错误的情况下,它们不会以任何方式改变优先级
  • 所有运算符,除了 andor、后缀 ifunlessuntilwhilerescue 比方法调用具有更高的优先级

让我们试试看:

class Noone < BasicObject
  undef_method :!

  def initialize(order)
    @order = order
  end

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

第一个一元:

# + 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

获得的分数:

  • not 在方法调用之后是 SyntaxError
  • 无论括号如何,所有一元运算符的优先级都高于方法调用

现在二进制:

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

获得的分数:

  • andor 方法调用的方括号是 SyntaxError
  • 我们必须在没有括号的情况下进一步测试 andor
  • ..... 呼叫 <=>。我们必须进一步测试
  • 我们无法以这种方式测试其他一些二元运算符,即 &&||==!=、修饰符 rescueifunlessuntilwhile
  • 除了上面提到的以外,运算符的优先级更高,与括号无关

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)

获得的分数:

  • andor 在没有括号的情况下具有较低的优先级
  • &&||==!= 具有更高的优先级,而不管括号

def five(*args)
  p args
  5
end

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

获得的分数:

  • ..... 具有更高的优先级,而不管括号

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)

获得的分数:

  • 括号 ifunlessuntilwhile 导致 SyntaxError
  • 以上所有的优先级都低于没有括号的方法调用

def error
  puts 'Error'
  raise
end

anything error rescue yes
anything(error rescue yes)

获得的分数:

  • rescue 周围的括号导致 SyntaxError
  • 如果没有括号,
  • rescue 的优先级较低

三元:

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

获得的分数:

  • 无论括号如何,三进制都具有更高的优先级

赋值(留到最后,因为它改变了 yesno):

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

获得的分数:

  • 赋值比调用具有更高的优先级

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