-5

I know that Class defines === to test whether an object is an instance of that class.

Now the question is why this evaluate to true only if Class is the lefthand operand.

Example:

'a' === String #false

and

String === 'a' #true

or

def Foo
end

f = Foo.new
f === Foo #false
Foo === f #true
styvane
  • 59,869
  • 19
  • 150
  • 156
  • 1
    http://gilesbowkett.blogspot.com/2007/11/what-is-threequals.html. TLDR: don't use it. You're right that for Class, it's defined to check if the right-hand-side is an instance, but for String, === is defined to check equality. – Amit Kumar Gupta Apr 02 '15 at 04:36
  • 2
    The only reason you are asking this question is because the method names `===` and `==` resemble each other. Would you ask why `3 / 2` is not the same as `2 / 3`? `String === 'abc'` is snytactic sugar for `String.===('abc')`. If the method were instead named `triple_equal`, we'd use it like this: `String.triple_equal('abc')`. Would you ask if that should be the same as `'abc'.triple_equal(String)`? – Cary Swoveland Apr 02 '15 at 04:52
  • @AmitKumarGupta, `...but for String, ===...` is a little confusing. I know you are referring to the comparison of two strings, but the reader might think you mean `String === 'cat'`. – Cary Swoveland Apr 02 '15 at 04:58
  • Why *should* calling a completely method on a completely different object of a completely different class with a completely different argument return the same result? – Jörg W Mittag Apr 02 '15 at 06:28
  • 1
    @JörgWMittag it's quite natural to expect a method resembling equality to be reflexive, **symmetric**, and transitive. When that's not the case, it's the *language* which is being exceptional and counter-conventional, not the *programmer's expectations*. – Amit Kumar Gupta Apr 02 '15 at 06:44
  • @AmitKumarGupta: Ruby is an object-oriented language. In an object-oriented language, you send messages to objects and it is completely up to that object how it responds to that message. It is, quite simply, *impossible* to have symmetric methods in OO, unless the two objects in question cooperate with each other. But in the general case, you can *never* expect symmetry in an object-oriented language. E.g., the classes in the `Numeric` hierarchy have a type coercion protocol which tries to ensure that `+` and `*` are symmetric, but you can easily create an object which simply doesn't follow … – Jörg W Mittag Apr 02 '15 at 06:57
  • … that protocol, and boom, addition is no longer symmetric. This is a fundamental property of OO, there's really nothing Ruby (or *any* OO language) can do about it. – Jörg W Mittag Apr 02 '15 at 06:58
  • @Michael yes it does. Your answer is right there. In the duplicated question. – Saturn Apr 02 '15 at 07:08
  • @JörgWMittag: you're missing the point. No OO language can guarantee that any method (defined for all objects, taking one argument) is symmetric, but a programmer can expect that the language designers have imparted semantics to the definitions in the standard library such that `===` is symmetric. In Ruby there's no guarantee that `<` is irreflexive because I can monkey-patch `Fixnum`, but if Ruby came out of the box saying `0 < 0` is true, you wouldn't say, "yup, makes sense, no guarantees in Ruby", you'd rightfully ask, "that defies convention and intuition, why would Matz do this?" – Amit Kumar Gupta Apr 02 '15 at 09:15
  • @AmitKumarGupta: Ah, I see. But `===` isn't equality, it's case subsumption, which by definition isn't symmetric. So, basically, there is no expectation *in general* that methods can be enforced to be symmetric, and there is no expectation *specifically* that case subsumption is symmetric (in fact, the idea doesn't even make sense), so I don't see how that is "exceptional" or "counter-conventional", or can you name any language where case subsumption or something equivalent is symmetric? – Jörg W Mittag Apr 02 '15 at 10:15
  • 1
    That's assuming OP knows that `===` is for case subsumption in the first place, but if OP knew that he wouldn't be asking the question. My comment was about a method "resembling equality". That's clearly the source of OP's confusion. The response to the question isn't, "don't you know how case subsumption works?", it's "I can see why you're confused, this thing that looks like it has something to do with equality is actually meant for something else, which sometimes coincides with equality (`==`)." – Amit Kumar Gupta Apr 02 '15 at 10:54

1 Answers1

10

Because

  • String === 'a' is the same as String.===('a'), which calls Class#===, inherited from Module#=== to test whether the parameter inherits from the receiver module; and

  • 'a' === String is the same as 'a'.===(String), which calls String#===, inherited from Object#=== to test whether the parameter is equal to the receiver object.

In other words, === is not symmetric; Object#=== and Module#=== are very different methods. There's also Regexp#===, Proc#===... that also do very different things, and are also asymmetric (match against pattern, execute with parameter(s)).

Amadan
  • 191,408
  • 23
  • 240
  • 301