简体   繁体   中英

Redefine precendence of operators in ruby

Using ruby, I can overload the operators in my functions. I wonder if I can overload the precedence somehow (cheats are allowed). For example:

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

This script prints 4 thanks to the precedence. How can I make it print 0 by evaluating first the sum then the multiplication?

I don't think you can do this without hacking Ruby itself; of course, doing this would probably break a non-trivial amount of all the other Ruby code you're using. You see, Ruby doesn't know what a , b , or c are when it is figuring out what

a + b * c

means, it only knows the built-in precedence of the + and * operators and how to translate those operators to method calls.

You could manually convert the operators to method calls and manually order them according to your preferred precedence:

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

but that's pretty nasty (less nasty than confusing everyone by changing the precedence of operators though).

An alternative would be to put "a + b * c" into a string and then write your own parser for that string. This would just be a fancy way of dynamically building a.+(b).*(c) though.

Then there's the obvious: use parentheses and leave the precedence alone:

((a + b) * c).value

Keep the full stack until it is evaluated at last.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM