On 13.03.2008 20:35, ara howard wrote:
> On Mar 12, 2008, at 7:14 PM, Trans wrote:
> 
>> Which approach is better: parametric module or an injecting class
>> method.
> 
> i would say neither and both.  it's saner to decouple them and then  
> recouple - giving the best of both worlds with the same amount of code:
> 
> 
> cfp2:~ > cat a.rb
> module Equate
>    module Methods
>      def equate a, b
>        module_eval <<-code
>          def ==(other)
>            self.#{ a } == other.#{ a } && self.#{ b } == other.#{ b }
>          end
>          def eql?(other)
>            self.#{ a }.eql?(other.#{ a }) && self.#{ b }.eql? 
> (other.#{ b })
>          end
>          def hash()
>            self.#{ a }.hash ^ self.#{ b }.hash
>          end
>        code
>      end
>    end
> 
>    def Equate.included other
>      other.send :extend, Methods
>    end
> 
>    def Equate.on a, b
>      Module.new{
>        include Equate
>        equate a, b
>      }
>    end
> end
> 
> class C < Struct.new(:a, :b)
>    include Equate.on(:a, :b)
> end
> 
> p C[4,2] == C[4,2] #=> true
> p C[4,2] == C[4,3] #=> false
> 
> class D < Struct.new(:a, :b)
>    include Equate
>    equate :a, :b
> end
> 
> p D[4,2] == D[4,2] #=> true
> p D[4,2] == D[4,3] #=> false
> 
> 
> 
> cfp2:~ > ruby a.rb
> true
> false
> true
> false

Using a Struct generated class as base class is a bad example IMHO
because those classes do already have the equation properties.

At the moment the only advantage I see in using modules is avoidance of 
namespace pollution.  Personally I'd just have a method in class Module 
equate_on which defines methods as shown.

Btw, while we're at it, I'd also like order_on which defines <=> based 
on fields given. :-)

Kind regards

	robert