From: Hugh Sasse Date: 2005-09-14T23:12:16+09:00 Subject: Re: Sets, uniqueness not unique. ---559023410-440155785-1126707084=:29921 Content-Type: MULTIPART/MIXED; BOUNDARY="-559023410-440155785-1126707084=:29921" This message is in MIME format. The first part should be readable text, while the remaining parts are likely unreadable without MIME-aware tools. ---559023410-440155785-1126707084=:29921 Content-Type: TEXT/PLAIN; charset=X-UNKNOWN; format=flowed Content-Transfer-Encoding: QUOTED-PRINTABLE On Wed, 14 Sep 2005, Mauricio Fern=E1ndez wrote: > The defaults are actually those of Hash. You can follow the call chain > starting from > > static struct st_hash_type objhash =3D { > rb_any_cmp, > rb_any_hash, > }; > > in hash.c. For user-defined classes, it will end up using #hash and #eql? > defined in Kernel. [rb_any_cmp and rb_any_hash have some extra logic for > Symbol, Fixnum and String values, and some core classes redefine the > associated methods]. > OK, it seems I'm thinking along the right lines now. Here is what I did in the end: --- /tmp/T0oTa4V2 Wed Sep 14 15:05:35 2005 +++ populate_tables.rb Wed Sep 14 15:01:24 2005 @@ -9,10 +9,31 @@ $debug =3D true +module StringCollection + + def hash + (self.class)::FIELDS.inject(MD5.new()) do |d,m| + d << send(m) + end.hexdigest.hex + end + + def eql?(other) + (self.class)::FIELDS.inject(true) do |b,v| + begin + b && (self.send(v) =3D=3D other.send(v)) + rescue + b =3D false + end + end + end + +end + class Student - attr_accessor :forename, :surname, :birth_dt, - :picture, :coll_status + include StringCollection + FIELDS =3D [:forename, :surname, :birth_dt, :picture, :coll_status] + FIELDS.each{|f| attr_accessor f } def initialize(forename0, surname0, birth_dt0, picture0, coll_status0) @@ -22,28 +43,22 @@ @picture =3D picture0 puts "in student.new() picture is #{picture0.inspect}, @picture is #{= @picture.inspect} " if $debug @coll_status =3D coll_status0 - @hash =3D FIELDS.inject(MD5.new()) do |d,m| - d << send(m) - end.hexdigest.hex end - def hash - @hash - end - def eql?(other) - self.hash =3D=3D other.hash - end - def to_s - "#{@surname}, #{@forename}, #{@birth_dt}, #{@picture}, #{@coll_status}= , #{@hash}" + "#{@surname}, #{@forename}, #{@birth_dt}, #{@picture}, #{@coll_status}= , #{hash}" end end class CourseModule - attr_accessor :aos_code, :dept_code, :aos_type, :full_desc + include StringCollection + + FIELDS =3D [:aos_code, :dept_code, :aos_type, :full_desc] + FIELDS.each{|f| attr_accessor f } + def initialize( aos_code, dept_code, aos_type, full_desc) @aos_code =3D aos_code @dept_code =3D dept_code I was particularly pleased to be able not to repeat the FIELDS, by means of attr_accessor, and that the idea of doing (self.class)::FIELDS actually worked. In the hope that this helps someone else, and thank you, Hugh ---559023410-440155785-1126707084=:29921-- ---559023410-440155785-1126707084=:29921--