使用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
?
答案 0 :(得分:4)
我不认为你可以在不破坏Ruby本身的情况下做到这一点;当然,这样做可能会破坏你正在使用的所有其他Ruby代码的非常重要的数量。你看,Ruby在弄清楚什么时不知道a
,b
或c
是什么
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