Really? It doesn't look much like it to me. The series of when
statements following a case statement without an expression work
pretty much like an if elsif...else sequence. WIth an expression in
the case statement like
case foo
when bar
baz
when bop
boo
else
shazbot
end
is equivalent to:
if bar === foo
baz
elsif bop === foo
boo
else
shazbot
end
Case is kind of like a macro, so I'll talk about case statements
expanding, but what's really happening is that the Ruby parser and
interpreter evaluate the code 'as if' it had been written as an
if;elsif...;else sequence.
Note that the logical expressions in the if and elsif clauses are ===
messages sent the the when value with the case value as the argument.
That's why === (with 3 equal signs) is called the case comparison
operator. Object defines === to be the same as == but certain classes
redefine it. In particular Range overrides it to be the same as
Range#include?
This 'expands' to
generation = if (1946..1963) === birthyear
"Baby Boomer"
elsif (1964..1976) === birthyear
"Generation X"
elsif 1(978..2000) === birthyear
"Generation Y"
else
nil
end
So the value of the case is determined by the first range which
includes birthyear.
Your code (I'm changing the ...s so we can distinguish the different 'legs'):
'expands' to:
winalloc = if (x == 1.50...2.50) === winunit
something1
elsif (x == 2.50...3.80) === winunit
something2
elsif (x == 3.80...5.50) === winunit
something3
else
something_else
end
We can see by the code above the case that x is a string (the result
of gets chomp), so all those x == <range> expressions will evaluate
to false since x is a string and not a Range. So if we substitute:
winalloc = if false === winunit
something1
elsif false === winunit
sometthing2
elsif false === winunit
something3
else
something_else
end
which can be simplified to:
winalloc = if false === winunit
something1
else
something_else
end
which should be obvious I hope.
Note that false, being the sole instance of FalseClass uses Object#===
so false === winunit will only be true if the variable winunit
references the unique false object.
So since we don't know what winunit actually is from the snippet
you've given, the result will either be something1 iff winunit ==
false, and something_else otherwise. If this is the first appearance
of winunit it will be nil, so the case expression will always return
something_else.
Note that since x is a string (the result of gets chomp) it won't be a
member of any of those ranges. I'm guessing that maybe winunit is
meant to be the integer value of that string. If so maybe you want
something like this:
x = gets.chomp
winunit = x.to_i
winalloc = case winunit
when 1.50...2.50: ...
when 2.50...3.80: ...
when 3.80...5.50: ...
else something
Which should look a lot more like the code in Matz and Flanigan.
HTH
--
Rick DeNatale
Blog:
http://talklikeaduck.denhaven2.com/
Github:
http://github.com/rubyredrick
Twitter: @RickDeNatale
WWR:
http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn:
http://www.linkedin.com/in/rickdenatale