From: "Aleksi Niemelä" Date: 2000-09-27T07:02:44+09:00 Subject: [ruby-talk:5143] Re: Types and === Hal asks: > # Are there any two types X and Y such that x===y and y===x both have > # meaning, and mean different things? Conrad helps: > Do relations like inside ... count as === case candidates? I was thinking much harder cases, but this one is really easy. Think that regexp.===(other) actually delegates to self.match(other) so the meaning of === is thought to be purely useful in context of String (or a class which implements to_s). If we take a Bag, and put stuff in it, we could argue that the Bag has other functions that merely containing something. So let's go one step higher - let's take a Container. Container merely has some stuff and it's main function is to contain. Thus Container#=== maps to Container#contains?. Now comes a lot of meaningless discussion, so if you're busy you should skip to the last paragraphs. So it makes sense to write case bought_object when shopping_bag puts "dull old you" when bag_of_tricks puts "hmm...you seem quite interesting person to me" else log "seems we have a hacker here, well, he can't misuse our systems" end Remember also there's a this weird cube with infinite surface and zero volume. So nothing could be inside it. Still you could easily stuff that thing in bag_of_tricks. There's no point, however, to claim it's an container - no it's purely an entertainer. It's main function is to surprise. There's entire group of entertaining wonders of world, and ZeroVolumeCube "implements" Entertainer interface, which among all fun things has a method to query if this entertainer is surprising. On the other hand, the cube surprise only people pondering it's essence, and ordinary data structures couldn't care less (even though the Hash would be compeletely green because of envy to other type of hash, which could contain infinite number of elements but take only constant space :). module Entertainer def surprising?; end end class ZeroVolumeCube def surprising?(target) case target when PeopleWare true when Hardware false when Software false when AlienFormOfLife true else false end end def ===(other) surprising?(other) end end Now, while my examples are purely made, and might not make any sense I could argue the functionality in above bought_object case should claim me as interesting person if I buy ZeroVolumeCubes. At the same time I might query of all the candidates in my space what I should do with them: tiny_zvc = ZeroVolumeCube.new(size => miniature) circus = Circus.new colosseum = Circus.new(size => CIRCUS::ENORMOUS) girl_candidate_space.each do |girl| case girl when tiny_zvc puts girl.details + " is just like I want it" when circus puts girl + " is fun company too" when colosseum puts girl + " is nice but simply can't afford her" when /ann/i puts girl.name + ", had too much of these" when Cook sure_choices << girl end end (OT note, few of my ex-girlfriends have 'nn' in their names, like Anna, Anne, Anne, Anne, Hanna, Hanna. B-} ) I hope I made clear few points. In any case I'd like to summarize them even if they just got more blurred: 1) the classes might not be interested in reproducing functionality of == in ===. 2) the classes will probably implement their only, sole interesting usage in ===. 3) the x == y is commutative, the x === y might not be The third point needs more argumentation. Take an example of the case of container (like a bag) which implements === as bag.contains?(object) and if object does not do === like a container does the results differ. Here's the catch. Even if the objects does the go of container (ZeroVolumeCube#contains? is trivial and really uninteresting for anything but claiming it's a special case of a container) we might not have same results. So, finally, as an example of (x===y) != (y===x) I can conclude bag.===(zero_volume_cube) #=> true zero_volume_cube.===(bag) #=> false Uh, let me be excused... :) - Aleksi