2

使用 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通过先计算总和然后计算乘法来打印它?

4

2 回答 2

4

我认为如果不破解 Ruby 本身就无法做到这一点。当然,这样做可能会破坏您正在使用的所有其他 Ruby 代码。a你看,Ruby 不知道是b什么c

a + b * c

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

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

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

但这非常令人讨厌(尽管通过更改运算符的优先级来混淆每个人都不那么讨厌)。

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

然后很明显:使用括号并保留优先级:

((a + b) * c).value
于 2013-09-07T04:59:42.973 回答
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
于 2013-09-07T05:25:40.540 回答