Mori
Mori

Reputation: 27779

Ruby operators as methods?

I'd like to try using Ruby in a more functional style, in which common operators are replaced with methods. I saw an example of this in Volt Framework where Object#or is used in place of ||, e.g.

x.or(y) == x || y

... which is implemented as

class Object
  def or(other)
    if self && !self.nil?
      self
    else
      other
    end
  end
end

Volt also implements Object#and. It would be nice to extend the same idea to other operators, like

x.eq(y)    == (x == y)
x.lt(y)    == x < y
x.times(y) == x * y
x.exp(y)   == x ** y

Arel::Predications are a nice collection of these for ActiveRecord attributes, but not for generic objects.

Are there any libraries or other examples available for this approach?

The only objection to it that I can think of is that it pollutes the Object namespace, risking collisions down the inheritance chain. (This could be minimized with a naming strategy, like Object#_or.) Are there other problems with it?

Upvotes: 2

Views: 148

Answers (2)

shock_one
shock_one

Reputation: 5925

The problem with or and and is that they're guaranteed to be short circuited. Due to Ruby's evaluation strategy it's impossible to implement these methods as a part of a library.

Other methods are, of course, possible, but I don't think it's a good idea. First of all, declaring, say, the method + on the class Object forces all the subclasses to implement the method, even if it doesn't make sense. What's User.find(1) + User.find(2)? Interface segregation principle warns you agains it. And secondly, you wouldn't have the syntactic sugar of the + method, you'd need to call it using the dot notation. Well, it's not really true for +, but I think you got the idea. Symbolic functions, like a >>= b aren't possible.

Upvotes: 2

Henrik N
Henrik N

Reputation: 16274

You have some of these in Ruby already.

There's a.eql?(b) and a.equal?(b) for equality, and you can even redefine the == and === methods. There's some nuance to what "equality" means exactly – see What's the difference between equal?, eql?, ===, and ==?.

The mathematical operators are methods: you can do 1.*(2) and you can redefine it:

class Fixnum
  def *(other)
    self + other
  end
end

2 * 5  # => 7

Upvotes: 2

Related Questions