Reflection, observ(er|able) instance vars?

I have an object for which equality tests take a long time, and I
have lots of others to compare it with. It is
an instance variable of my class, and it is also accessble by
attr_accessor. I'd like to hold a hash (number not Hash.new()) for
this object so I can compare it quickly with another. How do I detect that
it has changed so that the hash gets updated correctly? Does attr_accessor
construct code that leaves the right hooks in to detect this, or
must I write my own? Should attr_accessor do that if it doesn't?
Can I trap this by interposing in freeze tests, somehow?

If this is a code smell, how should I handle frequently queried,
slow-to-test, but changing instance variables? Make them all observables
and use update()? (That sounds expensive.)

        Thank you
        Hugh

I think the simplest solution it to define your own attribute writer
and always use it:

class Test
  attr_reader :my_attribute
  def my_attribute=(val)
    @my_attribute = val
    @my_attribute_hash = make_hash(val)
  end

  def some_other_method
    # Do this
    my_attribute = something_new
    # Not this!
    @my_attribute = something_else
  end
end

regards,
Ed

···

On Thu, Oct 20, 2005 at 09:01:45PM +0900, Hugh Sasse wrote:

I'd like to hold a hash (number not Hash.new()) for this object so I
can compare it quickly with another. How do I detect that it has
changed so that the hash gets updated correctly?

[...]

If only I could add it to object. I've tried, but _Why's metastuff
confuses me just sufficiently to stop me making the transition.

Given metaid.rb thusly:
<quote>
#!/usr/local/bin/ruby -w

···

On Fri, 21 Oct 2005, Edward Faulkner wrote:

On Thu, Oct 20, 2005 at 09:01:45PM +0900, Hugh Sasse wrote:
> I'd like to hold a hash (number not Hash.new()) for this object so I
> can compare it quickly with another. How do I detect that it has
> changed so that the hash gets updated correctly?

I think the simplest solution it to define your own attribute writer
and always use it:

#
# Due to Whytheluckystiff.
# http://www.whytheluckystiff.net/articles/seeingMetaclassesClearly.html
# Reformatted to work around bugs in vim indent.
#
#
class Object
  # The hidden singleton lurks behind everyone
  def metaclass
    class << self
      self
    end
  end
  def meta_eval &blk
    metaclass.instance_eval &blk
  end

  # Adds methods to a metaclass
  def meta_def name, &blk
    meta_eval { define_method name, &blk }
  end

  # Defines an instance method within a class
  def class_def name, &blk
    class_eval { define_method name, &blk }
  end
end

</quote>

and hashing.rb thusly:

<quote>
#!/usr/local/bin/ruby -w
#
# Make a class keep its hash up to date by using
# accessor methods that call hash on update.
#
# Hugh Sasse
# created: 20-OCT-2005
#
#

require 'metaid' # See http://www.whytheluckystiff.net/articles/seeingMetaclassesClearly.html

class Object
   def self.attr_hashing( *arr )
     attr_reader *arr
     arr.each do |var|
       meta_def var do |val|
         @var
       end
       vareq = (var.to_s + "=")
       meta_def vareq do |val|
         instance_variable_set( "@#{var}", val )
         self.hash
       end
     end
=begin
     class_def :initialize do
       self.class.traits.each do |k,v|
         instance_variable_set( "@#{k}", v )
       end
     end
=end
   end
end

</quote>

which I've produced from some badly aimed kicks at Dwemthy's Array,
I can't actually get the results I'd like.

<quote>
#!/usr/local/bin/ruby -w
#
# Test out the hashing prog.
#

require 'hashing'

class Wombat
  attr_hashing :wom, :bat
  attr_reader :thehash

  def initialize
    @wom = "wom"
    @bat = "bat"
    @thehash = hash
  end

  def hash
    puts "hash called"
    @thehash = (@wom.to_s + @bat.to_s).hash
  end

  def to_s
    @wom.inspect + @bat.inspect
  end
end

x = Wombat.new # produce the hash message
puts x
puts x.wom
puts x.bat
puts x.methods.sort.join(', ')
x.wom = "WOM" # produce the hash message
puts x.wom
x.bat = "BAT" # produce the hash message
puts x.bat
</quote>

Does anyone feel inclined to help me out? :slight_smile:

regards,
Ed

        Thank you,
        Hugh

You meant
  self.my_attribute = something_new
I think.

Regards,

Sean

···

On 10/20/05, Edward Faulkner <ef@alum.mit.edu> wrote:

def some_other_method
   # Do this
   my_attribute = something_new

Use Module, or better yet your own mixin. And just do the class eval
yourself w/o metaid, it's pretty easy

module HashAttr

   def attr_hashing( *arr )
     attr_reader *arr
     arr.each do |var|
       class_eval %{
         def #{var}(val) ; @var ; end
       }
       class_eval %{
         def #{var}=(val)
           @var=val
           @thehash = nil #reset
         end
       }
     end
   end

end

Then do

  class Wombat
    extend HashAttr

    attr_hashing :wom, :bat
    attr_reader :thehash

    def initialize
      @wom = "wom"
      @bat = "bat"
      @thehash = nil
    end

    def hash
      puts "hash called"
      @thehash ||= (@wom.to_s + @bat.to_s).hash
    end

    def to_s
      @wom.inspect + @bat.inspect
    end

    # compare
    def ==( other )
      hash == other.hash
    end
  end

HTH,
T.

Use Module, or better yet your own mixin. And just do the class eval
yourself w/o metaid, it's pretty easy

module HashAttr

   def attr_hashing( *arr )
     attr_reader *arr
     arr.each do |var|
       class_eval %{
         def #{var}(val) ; @var ; end
       }
       class_eval %{
         def #{var}=(val)
           @var=val
           @thehash = nil #reset
         end
       }
     end
   end

end

That's very nice! :slight_smile:

Then do

  class Wombat
    extend HashAttr

    attr_hashing :wom, :bat
    attr_reader :thehash

    def initialize
      @wom = "wom"
      @bat = "bat"
      @thehash = nil
    end

    def hash
      puts "hash called"
      @thehash ||= (@wom.to_s + @bat.to_s).hash
    end

    def to_s
      @wom.inspect + @bat.inspect
    end

    # compare
    def ==( other )
      hash == other.hash
    end
  end

HTH,

Yes, that's much simpler than the knots I'd got myself into. Thank
you. That will help considerably.

T.

        Hugh

···

On Fri, 21 Oct 2005, Trans wrote: