Reputation: 27779
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
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
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