Forum: Ruby case equality question

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
B4b39bb32dcaa75317b5ccea71080c36?d=identicon&s=25 Phil Meier (Guest)
on 2007-07-24 12:02
(Received via mailing list)
Hello

I do not understand the following code:

======
file = File.open('test.txt', 'r')
hash = {'file' => file, 'title' => 'title'}
hash.map { | param_key, param_value |
   puts "param_key = #{param_key}"
   puts "param_value = #{param_value}"
   puts "(param_value === String) = #{(param_value === String)}"
   case param_value
     when String
       puts "This is a String!"
     when File
       puts "This is a File!"
     else
       puts "Neither String nor File!!!"
   end
}
file.close
===

When I run this code the output is as follows:
param_key = title
param_value = title
(param_value === String) = false
This is a String!
param_key = file
param_value = #<File:0x2b689b8>
(param_value === String) = false
This is a File!

Why does Ruby goes to the when String case even if (param_value ===
String) is false?

BR Phil
B57c5af36f5c1f33243dd8b2dd9043b1?d=identicon&s=25 F. Senault (Guest)
on 2007-07-24 12:08
(Received via mailing list)
Le 24 juillet 2007 à 11:55, Phil Meier a écrit :

> Why does Ruby goes to the when String case even if (param_value ===
> String) is false?

I've been very suprised with this recently, but...

>> 'a' === String
=> false
>> 1 === String
=> false

>> String === 'a'
=> true
>> String === 1
=> false

Fred
7a561ec0875fcbbe3066ea8fe288ec77?d=identicon&s=25 Sebastian Hungerecker (Guest)
on 2007-07-24 12:10
(Received via mailing list)
Phil Meier wrote:
> Why does Ruby goes to the when String case even if (param_value ===
> String) is false?

Because it checks whether String===param_value and not
param_value===String.


HTH,
Sebastian Hungerecker.
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2007-07-24 12:12
(Received via mailing list)
Hi --

On Tue, 24 Jul 2007, Phil Meier wrote:

>  puts "(param_value === String) = #{(param_value === String)}"
> ===
>
> Why does Ruby goes to the when String case even if (param_value === String)
> is false?

Because String === param_value is true :-)  That's how the case thing
works:

   obj = Object.new
   def obj.===(other)
     puts "I'm being cased!"
     true
   end

   case "blah"
     when obj
   end

Output:

   I'm being cased!

because obj === "blah" is being called.


David
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2007-07-24 12:14
(Received via mailing list)
Hi --

On Tue, 24 Jul 2007, F. Senault wrote:

> => false
>
>>> String === 'a'
> => true
>>> String === 1
> => false

Don't be surprised -- it would be very weird the other way.  You'd
have to do:

   case String
   when "abc"

and so forth.  It wouldn't really be useable as the basis of a case
structure.


David
5dbb7a37b65f9e4ed415a97ab39300e5?d=identicon&s=25 Kaldrenon (Guest)
on 2007-07-24 16:01
(Received via mailing list)
Hm...I'm not sure I like that it doesn't go the other way. I like it
when code is easily converted to plain speech, when a line can be read
across quickly. And this seems to break that. Maybe not, but here's
how I see it:

b === a checks if a is-a b, right? Well isn't it a lot easier to read/
write/say "A is a B" than "B is instantiated in A" or "An example of B
is A"? Maybe this is a semantic quibble, but since English speakers
(and consequently a majority of the programming community) read left
to right, wouldn't it make more sense to have it behave this way?

It wouldn't even necessarily break case statements, since the .===
method would be part of all of the basic type classes (Fixnum/String/
etc) and there's always .class

This is just my opinion, and I admit to not knowing a lot yet. But I
figured I'd voice my thoughts.
Ef3aa7f7e577ea8cd620462724ddf73b?d=identicon&s=25 Rob Biedenharn (Guest)
on 2007-07-24 16:29
(Received via mailing list)
On Jul 24, 2007, at 10:00 AM, Kaldrenon wrote:
>
> It wouldn't even necessarily break case statements, since the .===
> method would be part of all of the basic type classes (Fixnum/String/
> etc) and there's always .class
>
> This is just my opinion, and I admit to not knowing a lot yet. But I
> figured I'd voice my thoughts.

case some_obj
when String
   # do String stuff with some_obj
when 50..100
   # do number stuff with some_obj
end

Perhaps you just need to think of different language when you want to
"read" the code:

"When String recognized some_obj, do String stuff with some_obj; when
the range 50 to 100 recognizes some_obj, do number stuff with some_obj."

The way in which Class constants (like String or Fixnum) recognize
(apply ===) happens to be an "is a?" test is happy arrangement.

You could even go further and read that as:

"Focus on some_obj and when String recognizes it, ..."

To distinguish the "case expr when obj" from the "case when expr"
form that is much closer to an "if-elsif-else" construct.

-Rob

Rob Biedenharn    http://agileconsultingllc.com
Rob@AgileConsultingLLC.com
7a561ec0875fcbbe3066ea8fe288ec77?d=identicon&s=25 Sebastian Hungerecker (Guest)
on 2007-07-24 16:31
(Received via mailing list)
Kaldrenon wrote:
> Hm...I'm not sure I like that it doesn't go the other way.

Wouldn't work.


> b === a checks if a is-a b, right?

Only if b is a class. If b is e.g. a range or an array, it checks
whether b
includes a. If b is a regex it checks whether b matches a. For many
other
things it's just the same as b==a.


> It wouldn't even necessarily break case statements, since the .===
> method would be part of all of the basic type classes (Fixnum/String/
> etc) and there's always .class

There's always .class, but that doesn't help you unless you assume that
the
argument passed to === will always be a class, which it won't.
5dbb7a37b65f9e4ed415a97ab39300e5?d=identicon&s=25 Kaldrenon (Guest)
on 2007-07-24 16:46
(Received via mailing list)
On Jul 24, 10:28 am, Sebastian Hungerecker <sep...@googlemail.com>
wrote:
> Only if b is a class. If b is e.g. a range or an array, it checks whether b
> includes a. If b is a regex it checks whether b matches a. For many other
> things it's just the same as b==a.

Okay, that's a more logical way of thinking about it, thank you. See,
I was looking at === as equivalent to Java's instanceof keyword, but I
can see now that that's not all === does.

Thanks for helping me clear it up.
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2007-07-24 17:47
(Received via mailing list)
Hi --

On Tue, 24 Jul 2007, Kaldrenon wrote:

> On Jul 24, 10:28 am, Sebastian Hungerecker <sep...@googlemail.com>
> wrote:
>> Only if b is a class. If b is e.g. a range or an array, it checks whether b
>> includes a. If b is a regex it checks whether b matches a. For many other
>> things it's just the same as b==a.
>
> Okay, that's a more logical way of thinking about it, thank you. See,
> I was looking at === as equivalent to Java's instanceof keyword, but I
> can see now that that's not all === does.

=== is a method, so its behavior is completely programmable per class
or per object.  That's why you get things like:

  /abc/ === "abcdef"    # true

One fairly generalized way to read a === b is: a is the case of b.
You might need to embellish it a bit, but it gives you a start:

   (matching) /abc/ is the case of "abcdef"
   (being an instance of) String is the case of "abc"

etc.


David
This topic is locked and can not be replied to.