Achieving Equality

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.

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 ?

On 7/6/06, Chris H. [email protected] 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.

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.

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

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.

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.

[email protected] 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