在ruby中定义运算符的优先级

时间:2013-09-07 04:36:11

标签: ruby

使用ruby,我可以在我的函数中重载运算符。我想知道我是否可以某种方式超载优先权(允许作弊)。例如:

class Odd
  attr_accessor :value
  def initialize(value)
    @value = value
  end

  def +(odd)
    Odd.new(@value - odd.value)
  end

  def *(odd)
    Odd.new(@value / odd.value)
  end
end

a = Odd.new(5)
b = Odd.new(5)
c = Odd.new(5)

puts (a + b * c).value

由于优先级,此脚本打印4。如何通过首先计算总和然后乘法来打印0

2 个答案:

答案 0 :(得分:4)

我不认为你可以在不破坏Ruby本身的情况下做到这一点;当然,这样做可能会破坏你正在使用的所有其他Ruby代码的非常重要的数量。你看,Ruby在弄清楚什么时不知道abc是什么

a + b * c

表示,它只知道+*运算符的内置优先级以及如何将这些运算符转换为方法调用。

您可以手动将运算符转换为方法调用,并根据您的首选优先级手动对它们进行排序:

a.+(b).*(c).value

但这非常令人讨厌(不过比通过改变运营商的优先级来混淆每个人而讨厌)。

另一种方法是将"a + b * c"放入一个字符串中,然后为该字符串编写自己的解析器。这只是动态构建a.+(b).*(c)的一种奇特方式。

然后就是显而易见的:使用括号并保留优先权:

((a + b) * c).value

答案 1 :(得分:2)

保留完整堆栈,直到最后评估。

class Odd
  attr_reader :stack
  def initialize *stack; @stack = stack end
  def + other; Odd.new(*(stack + [:-] + other.stack)) end
  def * other; Odd.new(*(stack + [:/] + other.stack)) end
  def value
    while i = stack.index(:-) do stack[i - 1, 3] = stack[i - 1] - stack[i + 1] end
    while i = stack.index(:/) do stack[i - 1, 3] = stack[i - 1] / stack[i + 1] end
    stack.first
  end
end

a = Odd.new(5)
b = Odd.new(5)
c = Odd.new(5)

puts (a + b * c).value
# => 0