# Achieving Equality

**URL:** <https://www.ruby-forum.com/t/achieving-equality/97392>\
**Category:** Ruby\
**Created:** [July 6, 2006, 8:19pm UTC](https://www.ruby-forum.com/t/achieving-equality/97392 "2006-07-06T20:19:23Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [July 6, 2006, 8:19pm UTC](https://www.ruby-forum.com/t/achieving-equality/97392/1 "2006-07-06T20:19:23Z")

</div>

I have this fancy class:

# Read from one and write to another.

class RWDelegator

```
def initialize( read, write )
  @read = read
  @write = write
end

def inspect
  "#{@read.call.inspect}*"
end

def ==( other )
  @read.call == other
end

def method_missing( meth, *args, &blk )
  read = @read.call
  ditto = read.dup
  result = ditto.send( meth, *args, &blk )
  if ditto != read
    result = @write.call.send( meth, *args, &blk )
  end
  result
end

```

end

I’m can’t achieve equlity when:

a, b = 1, 1  
r, w = lambda{ a }, lambda{ b }  
rwd = RWDelegator.new( r, w )  
rwd == a #=\> true  
a == rwd #=\> false

Any hope?

T.

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [July 6, 2006, 8:31pm UTC](https://www.ruby-forum.com/t/achieving-equality/97392/2 "2006-07-06T20:31:36Z")

</div>

unknown wrote:

> # Read from one and write to another.
> 
> class RWDelegator  
> …  
> end
> 
> I’m can’t achieve equlity when:
> 
> a, b = 1, 1  
> r, w = lambda{ a }, lambda{ b }  
> rwd = RWDelegator.new( r, w )  
> rwd == a #=\> true  
> a == rwd #=\> false
> 
> Any hope?
> 
> T.

I get a == rwd #=\> true ?

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [July 6, 2006, 8:45pm UTC](https://www.ruby-forum.com/t/achieving-equality/97392/3 "2006-07-06T20:45:43Z")

</div>

On 7/6/06, Chris H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I get a == rwd #=\> true ?  
> As do I:

$ cat test.rb  
class RWDelegator  
def initialize( read, write )  
@read = read  
@write = write  
end

```
def inspect
  "#{@read.call.inspect}*"
end

def ==( other )
  @read.call == other
end

def method_missing( meth, *args, &blk )
  read = @read.call
  ditto = read.dup
  result = ditto.send( meth, *args, &blk )
  if ditto != read
    result = @write.call.send( meth, *args, &blk )
  end
  result
end

```

end

a, b = 1, 1  
r, w = lambda{ a }, lambda{ b }  
rwd = RWDelegator.new( r, w )  
puts rwd == a  
puts a == rwd

$ ruby -v test.rb  
ruby 1.8.4 (2005-12-24) [i386-linux]  
true  
true

Jacob F.

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [July 6, 2006, 8:48pm UTC](https://www.ruby-forum.com/t/achieving-equality/97392/4 "2006-07-06T20:48:53Z")

</div>

Chris H. wrote:

> > T.
> 
> I get a == rwd #=\> true ?

Ah, it’s simplified example of what I’m actually doing. So in this case  
the integers auto-coerce it seems. Try:

```
a, b = "1", "1"

```

Which is probably a clue that can can be doen via #coerce, but I’m not  
sure how.

T.

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [July 6, 2006, 9:11pm UTC](https://www.ruby-forum.com/t/achieving-equality/97392/5 "2006-07-06T21:11:20Z")

</div>

unknown wrote:

> > I get a == rwd #=\> true ?
> 
> Ah, it’s simplified example of what I’m actually doing. So in this case  
> the integers auto-coerce it seems. Try:
> 
> ```
> a, b = "1", "1"
> 
> ```
> 
> Which is probably a clue that can can be doen via #coerce, but I’m not  
> sure how.
> 
> T.

I suggest modifying your == method to:  
def ==( other )  
#p “#{@read.call} == #{other.inspect}”  
if other.kind\_of?(RWDelegator)  
other == @read.call  
else  
@read.call == other  
end  
end

To compare to other objects you can:

1. write conversion methods (i.e. to\_s) and than convert the RWDelegator  
to the appropriate type when comparing (i.e. rwd.to\_s == “1”)

2. re-write the conversion methods of the other classes to handle your  
RWDelegator class appropriately:  
class String  
alias old== ==  
def ==(other)  
if other.kind\_of(RWDelegator)  
other == self  
else  
old==(other)  
end  
end

Cheers

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [July 6, 2006, 11:11pm UTC](https://www.ruby-forum.com/t/achieving-equality/97392/6 "2006-07-06T23:11:50Z")

</div>

Chris H. wrote:

> To compare to other objects you can:  
> else  
> old==(other)  
> end  
> end

Thanks! Your suggestions gave me this idea:

class RWDelegator

def initialize( write, &read )  
@read = read  
@write = write

```
read_class = @read.call.object_class

unless read_class.method_defined?(:eq_with_rwdelegator?)
  read_class.class_eval %{
    def eq_with_rwdelegator?( other )
      if RWDelegator === other
        other == self
      else
        eq_without_rwdelegator?(other)
      end
    end
    alias_method :eq_without_rwdelegator?, :==
    alias_method :==, :eq_with_rwdelegator?
  }
end

```

end

…

T.

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [July 7, 2006, 9:05am UTC](https://www.ruby-forum.com/t/achieving-equality/97392/7 "2006-07-07T09:05:12Z")

</div>

Srinivas JONNALAGADDA wrote:

> > ```
> > read_class.class_eval %{
> > end
> > 
> > ```
> > 
> > end
> > 
> > …
> > 
> > T.
> 
> The above approach would not scale seamlessly should you have another  
> RWDelegator-like class.

Any suggestions to fix?

> I would be interested in knowing the situation that required something  
> like this.

It is for method Annotations. The problem here is that annotations are  
inherited. So when readin them you want to see the merged result from  
the current class (receiver) up through Kernel itself. But when you are  
writting to them you want to just effect the the current class. Here’s  
an example::

class Y  
ann :a, :foo =\> [1]  
end

class X \< Y  
ann :a, :bar =\> [2]  
end

Y.ann.a #=\> #  
X.ann.a #=\> #  
X.ann.a.foo \<\< 2  
X.ann.a #=\> #  
Y.ann.a #=\> #

In the past, one had to do

X.ann.a.foo! \<\< 2

for this to work. Perhaps the overhead of th RWDelegator is too much  
and I should go back to the original way? Even so, it was quite a  
challenge to ge the above to work.

T.

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [July 7, 2006, 6:57am UTC](https://www.ruby-forum.com/t/achieving-equality/97392/8 "2006-07-07T06:57:19Z")

</div>

removed\_email\_address@domain.invalid wrote:

> ```
> def eq_with_rwdelegator?( other )
> 
> ```
> 
> end
> 
> …
> 
> T.

The above approach would not scale seamlessly should you have another  
RWDelegator-like class.

I would be interested in knowing the situation that required something  
like this.

JS
