======
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?
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.
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.
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.
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.
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 forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.