Case equality question

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

Le 24 juillet 2007 à 11:55, Phil M. 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

Phil M. 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 H…

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

Hi –

On Tue, 24 Jul 2007, Phil M. 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 :slight_smile: 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

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.

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 B. http://agileconsultingllc.com
[email protected]

On Jul 24, 10:28 am, Sebastian H. [email protected]
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.

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.

Hi –

On Tue, 24 Jul 2007, Kaldrenon wrote:

On Jul 24, 10:28 am, Sebastian H. [email protected]
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