From: flebber Date: 2011-01-14T20:40:45+09:00 Subject: Re: Case statements - Just beautification On Jan 13, 7:25 am, Rick DeNatale wrote: > On Thu, Jan 13, 2011 at 5:35 AM, flebber wrote: > > On Jan 13, 6:41 pm, Tim Roberts wrote: > >> flebber wrote: > >> >I just want to clarify case statements the name after the word case is > >> >this just for beautification and to help with code readability? What > >> >purpose does it serve. > > >> >So in my code its "winunit" and matz's code its "birthyear". > > >> ># Method 1 - Confident - assign range > >> ># number -> number > >> >def pricerange(x) > >> >puts "Enter the quoted price: " > >> >x = gets.chomp > >> >winalloc = case winunit > >> >  when x == (1.50...2.50) then ... > >> >  when x == (2.50...3.80) then ... > >> >  when x == (3.80...5.50) then ... > >> >  else something > >> >end > > >> Perhaps its purpose would be clearer if you wrote it like Matz's code: > > >> x = gets.chomp > >> winalloc = case x > >>   when (1.50...2.50) then ... > >>   when (2.50...3.80) then ... > >>   when (3.80...5.50) then ... > >>   else something > >> end > >> -- > >> Tim Roberts, t...@probo.com > >> Providenza & Boekelheide, Inc. > > > I tough my code looked like Matz's > > 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? > > > Matz's code > > # Case expression tests ranges with === > > generation = case birthyear > >             when 1946..1963: "Baby Boomer" > >             when 1964..1976: "Generation X" > >             when 1978..2000: "Generation Y" > >             else nil > >             end > > 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'): > > > My Code - (...) are placeholders > > x = gets.chomp > > winalloc = case winunit > >          when x == 1.50...2.50: something1 > >          when x == 2.50...3.80: something2 > >          when x == 3.80...5.50: something3 > >          else something_else > > '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 == 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 Thanks for the explanation. Yes that clears up the question.