Duplicity in Set

Hello,

I have a Set which should contains elements of my object Component. The
component class implements method hash. I'm gathering data, createing
Componets from them and storing it into the Set. It's a Set just to prevent
duplicates. But finally the Set contains duplicate elemets -- with the same
hash value.

Few snippets from the code:

$components = Set.new # declaration of the Set variable
.... then some addings to $components ...
$components.each {|c| puts(c.name + ', class:' + c.class.name + ', hash:' +
c.hash.to_s)}

And it prints:

OR-copm2.2, class:Component, hash:304328379
OR-copm2.2, class:Component, hash:304328379

The Component class is defined in this way:

Class Component
    attr_reader :attributes, :name, :subcomponents
    attr_writer :attributes # array of Attribute objects

    def assembly?
        @subcomponents.length != 0
    end

    def object_id
        @name.object_id
    end

    def hash
        @name.hash
    end

    def initialize(name)
        @name = name
        @attributes = Hash.new
        @subcomponents = Array.new
    end
end

What am I doing wrong?

Thanks,
Radek

You must implement #eql? and #hash --

require 'set'

class Component
   attr_accessor :attributes
   attr_reader :name, :subcomponents
   def initialize(name)
     @name = name
     @attributes = {}
     @subcomponents =
   end
   def inspect() %{<%s hash=%#x @name=%s>} % [self.class.name, self.hash, @name.inspect] end
   def eql?(other) @name.eql?(other.name) end
   def hash() @name.hash end
end

components = Set.new
components << Component.new("foo")
components << Component.new("bar")
components << Component.new("foo")
components.each { |c| puts c.inspect }

-- Daniel

···

On Apr 11, 2006, at 12:28 PM, Radek Skokan wrote:

I have a Set which should contains elements of my object Component. The
component class implements method hash. I'm gathering data, createing
Componets from them and storing it into the Set. It's a Set just to prevent
duplicates. But finally the Set contains duplicate elemets -- with the same
hash value.

Thanks Daniel, I omitted the eql?. Now it works.
Radek

···

On 4/11/06, Daniel Harple <dharple@generalconsumption.org> wrote:

On Apr 11, 2006, at 12:28 PM, Radek Skokan wrote:

> I have a Set which should contains elements of my object Component.
> The
> component class implements method hash. I'm gathering data, createing
> Componets from them and storing it into the Set. It's a Set just to
> prevent
> duplicates. But finally the Set contains duplicate elemets -- with
> the same
> hash value.

You must implement #eql? and #hash --

require 'set'

class Component
   attr_accessor :attributes
   attr_reader :name, :subcomponents
   def initialize(name)
     @name = name
     @attributes = {}
     @subcomponents =
   end
   def inspect() %{<%s hash=%#x @name=%s>} % [self.class.name,
self.hash, @name.inspect] end
   def eql?(other) @name.eql?(other.name) end
   def hash() @name.hash end
end

components = Set.new
components << Component.new("foo")
components << Component.new("bar")
components << Component.new("foo")
components.each { |c| puts c.inspect }

-- Daniel