ruby picture

RCR 199: add Object#identical? and change behaviour of Object#equal?

Submitted by coreywangler (Wed Jan 21 04:01:44 UTC 2004)

Abstract

The ideas of equivalency and identity are not represented consistently by the current method names. This proposal deals with this issue by having Object#equal? behave as an equivalency test, and introducing Object#identical? as an identity test.

Problem

Current meaning of Object#equal? is not consitent with the ideas of equivalence and identity.

Proposal

Add Object#identical? to check for identical objects (i.e. the current behaviour of Object#equal?).

Change behaviour of the Object#equal? method to check for equivalency of value and class. The method can then be thought of as to mean "more equivalent" than Object#eql?, and would be useful for testing the equivalency of duplicates and clones.

Analysis

The following code is an example of what is proposed:


    
  class Object
    def identical?( other )
      self.id == other.id
    end
    def equal?( other )
      (self.class.id == other.class.id) and self.eql?(other)
    end
  end
  @test_fmt = "%12s : %7s %8s %9s %10s\n"
  def test_head
    printf @test_fmt, "func", "==", "eql?", "equal?", "identical?"
  end
  def test(x_name, y_name, x, y)
    printf @test_fmt, x_name+'.func('+y_name+')', 
           x==y, x.eql?(y), x.equal?(y), x.identical?(y)
  end
  z = Array.new.concat([1,2,3])
  a = z
  b = a.dup
  c = a.dup; c[0]=1.0
  class Array2 < Array
  end
  b2 = Array2.new.concat([1,2,3])
  c2 = b2.dup; c2[0]=1.0
  test_head; \
    test('a','z',a,z); \
    test('b','z',b,z); \
    test('b2','z',b2,z); \
    test('c','z',c,z); \
    test('c2','z',c2,z)
  #
  #        func :      ==     eql?    equal? identical?
  #   a.func(z) :    true     true      true       true
  #   b.func(z) :    true     true      true      false
  #  b2.func(z) :    true     true     false      false
  #   c.func(z) :    true    false     false      false
  #  c2.func(z) :    true    false     false      false
  #

    

Changing Object#equal? to have behaviour of an equivalency test avoids confusion, because its meaning is then consistent with the other equivalency methods (eql?, ==, ===).

By making the Object#equal? method test for equivalency of value and class, it becomes a useful method for testing equivalence of dup'ed or clone'ed objects.

Using Object#identical? to check if objects are identical (same object id) makes more sense because the method does what you would expect it to do.

Implementation

Have Object#identical? do what Object#equal? currently does.
Also, change behaviour of the Object#equal? method.

The following code is an example of what is required.


    
  class Object
    def identical?( other )
      self.id == other.id
    end
    def equal?( other )
      (self.class.id == other.class.id) and self.eql?(other)
    end
  end

    

ruby picture
Comments Current voting

Why should we introduce incompatibility by changing basic method behavior, when virtually no one has had troubles about these names? "identity?" may be better than "equal?", but I'm not sure it's good enough to change.

-matz.


Certainly this is something that would have to be phased-in slowly. But I agree, Ruby is a bit too numerous with concepts (and thus methods) of equality. Using identity to help contrast the extremity of absolute sameness would, I believe, be helpful, especially to the nuby (and indeed the nuby in all of us b/c we all sometimes forget).

-T.


IMHO, being equivalent (or "equal") is a totally different concept to being identical. When learning ruby (well, I still have a long way to go!) this area required more thinking than necessary due to the mixing of these two concepts.

Deprecating #equal? and replacing with #identical? would remove this issue.

I suggested a new behaviour for #equal? that is in line with the current equivalency methods. Maybe deprecating #equal? without replacing it with a new behaviour would address your concern regarding incompatability?

Yes, I am being picky. I really admire the clarity that the ruby language has, and I'm just suggesting an (albeit small) improvement to that clarity. Yes, developers can learn almost anything that is in a language... but the aim is to have less to learn, isn't it?

Note that I have made a small change to the proposal. #equal? implementation now uses #eql? instead of == in the expression, making it more in line with the "more equal" theme.

-corey.


Here I'm going to start arguing with myself... ;)

One line of thinking could be that being identical is another shade of being "more equal". Also, introducing another method name in this area is another thing to remember in itself.

As for clones/duplicates, is it useful to have #equal? with the suggested behaviour?


          
  ==         -- pretty much the same value   1 == 1.0  gives true
  eql?       -- the same value               1.eql?(1.0) gives false
  equal?     -- same value and same class (a clone or duplicate object)
  identical? -- is identical, i.e. the same object
-corey.
          


I don't think we should change equal?. But I agree that it appears someway misleading. I think object.same?(other) could be cool :)


I was thinking that "Object#identical?" is more in line with "Object#id" (identity/identifier), but "Object#same?" would work too (less typing may be a bonus ;-).

-corey.


I can't help thinking that a.id == b.id isn't so bad....

David Black


Yep, so maybe don't have an #identical? or #same? method at all. What would you suggest happen to #equal?

  • Leave it as is (meaning "identical")
  • Deprecate it without any replacement method
  • Change its behaviour to "same value and same class"

-corey.


I'd choose "leave it as is". They are "equal" in a sense of identity.

-- matz


Yep, cool. Thanks everyone for your input. Withdrawing this RCR.

-corey.


Strongly opposed 0
Opposed 4
Neutral 0
In favor 5
Strongly advocate 2
ruby picture
If you have registered at RCRchive, you may now sign in below. If you have not registered, you may sign up for a username and password. Registering enables you to submit new RCRs, and vote and leave comments on existing RCRs.
Your username:
Your password:

ruby picture

Powered by .