Skip to content

Instantly share code, notes, and snippets.

@jcoglan
Created October 27, 2008 14:33
Show Gist options
  • Save jcoglan/20107 to your computer and use it in GitHub Desktop.
Save jcoglan/20107 to your computer and use it in GitHub Desktop.
# A possibly misguided attempt to introduce automatic operator commutativity to Ruby. Say
# I add a '+' method to Range so that for example:
#
# (3..7) + 12 #=> (15..19)
#
# I'd expect to be able to call '12 + (3..7)' and get the same answer. This means I need
# to override Fixnum#+, meaning my new addition operator is expressed in two places. This
# module generates methods that automatically fill in the gaps so you only need to express
# the semantics of an operator in a single method, in a single class.
#
# A simple example:
#
# class Range
# def +(num)
# (first + num)..(last + num)
# end
# end
#
# class Fixnum
# include Commutativity
# end
#
# 4 + (1..15)
# #=> (5..19)
#
# The module covers binary arithmetic, logic and comparison operators.
#
module Commutativity
ALL_SYMBOLS = %w(** ~ + - * / % << >> & ^ | <= < > >= <=> == === =~)
COMMUTATIVE = %w(+ * & ^ | == === =~)
NEGATED = %w(- <=>)
INVERTED = %w(/)
OPPOSITES = [%w(<< >>), %w(<= >), %w(< >=)]
TRANSLATIONS = {
COMMUTATIVE => lambda { |object, symbol, value| value.__send__(symbol, object) },
NEGATED => lambda { |object, symbol, value| -value.__send__(symbol, object) },
INVERTED => lambda { |object, symbol, value| 1.0 / value.__send__(symbol, object) }
}
def self.included(mod)
mod.module_eval do
TRANSLATIONS.each do |list, translation|
list.each do |symbol|
orig = instance_method(symbol) rescue nil
define_method(symbol) do |value|
begin
orig.bind(self).call(value)
rescue
translation.call(self, symbol, value)
end
end
end
end
OPPOSITES.each do |pair|
pair.each_with_index do |symbol, i|
orig = instance_method(symbol) rescue nil
define_method(symbol) do |value|
begin
orig.bind(self).call(value)
rescue
not value.send(pair[(i+1)%2], self)
end
end
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment