From: Robert Klemme Date: 2003-05-21T01:53:36+09:00 Subject: Re: Ruby reference recommendations This is a multi-part message in MIME format. ------=_NextPart_000_0016_01C31F00.A4E889F0 Content-Type: text/plain; charset="iso-8859-2" Content-Transfer-Encoding: quoted-printable X-MIME-Autoconverted: from 8bit to quoted-printable by funfun.nagaokaut.ac.jp id h4KGrlG61859 "Marcin 'Qrczak' Kowalczyk" schrieb im Newsbeitrag news:200305201459.13367.qrczak@knm.org.pl... > Dnia wto 20. maja 2003 12:11, Robert Klemme napisa=B3: > > > :-)) And you have to include Java in the list - because of its primitive > > types. > > Well, in some respects it doesn't matter that they are represented > differently, since they are immutable. You can think about them as references > to immutable number objects. They are passed to functions and returned from > them and stored in data structures in the same way as regular objects. > Arithmetic operations always return the same object for the given value= , so > =3D=3D works as for references. True. > The only conceptual differences are when you can't implicitly coerce them to > object class and back, that "references" to them can't be nil, that you can't > synchronize on them, and perhaps other things like this. And it's bad that > identity is the "default" equivalence, which happens to work on primitive > types and mutable objects. It does not work for mutable instances whose equivalence is state based and not identity based. > Immutable objects should be always compared by > value - this includes immutable strings and large numbers, but in Java the > proper comparisons for them are different than for ints. Since there is no way in Java to define a class a having immutable instances IMHO the approach taken in Java (and in Ruby also) is the most reasonable one. When implementing classes that should behave like String and Integer, i.e., equality is dependent on state and not identity, peopl= e have to take this into consideration and override the appropriate methods (hashCode() and equals() for Java). In ruby we can do module StateEquivalent def eql?(obj) return false unless self.class =3D=3D obj.class (self.instance_variables + obj.instance_variables).uniq.each do |var| v1 =3D self.instance_eval var v2 =3D obj.instance_eval var return false unless v1 =3D=3D v2 end return true end def =3D=3D(obj); eql? obj; end end (see attached script for test) Regards robert ------=_NextPart_000_0016_01C31F00.A4E889F0 Content-Type: application/octet-stream; name="equivalencer.rb" Content-Disposition: attachment; filename="equivalencer.rb" Content-Transfer-Encoding: 7bit module StateEquivalent def eql?(obj) return false unless self.class == obj.class (self.instance_variables + obj.instance_variables).uniq.each do |var| # p var v1 = self.instance_eval var v2 = obj.instance_eval var return false unless v1 == v2 end return true end def ==(obj); eql? obj; end end class Foo include StateEquivalent attr_accessor :x,:y end def test_equal( a, b ) puts ">>" p a p b ["a.equal?( b )", "b.equal?( a )", "a == b", "b == a"].each do |expr| puts "#{expr} : #{eval expr}" end puts "<<" end f1 = Foo.new f1.x=10 f1.y=20 f2 = Foo.new f2.x=10 f2.y=20 f3 = Foo.new f3.x=10 f4 = Foo.new f4.x=10 f4.y=nil f5 = Foo.new f5.x=10 test_equal f1, f2 test_equal f1, f3 test_equal f4, f5 __END__ module StateEquivalent def eql?(obj) return false unless self.class == obj.class iv = self.instance_variables iv.each do |var| # p var v1 = self.instance_eval var v2 = obj.instance_eval var return false unless v1 == v2 end # now ensure all values defined in the other instance # but not here are nil (obj.instance_variables - iv).each do |var| # p var v2 = obj.instance_eval var return false unless v2.nil? end return true end def ==(obj); eql? obj; end end ------=_NextPart_000_0016_01C31F00.A4E889F0--