<, >, and ranges in a case statement

I feel like this should be simple but i can't figure it out.

In a case statement, i know how to use ranges to compare against the
given variable. But how do i use < or > ? eg i want to do this:

age = 25

category = case age
  when < 12 : "child"
  when 13..17 : "minor"
  when 18..24 : "young ad*lt"
  when 25..49 : "ad*lt"
  when 50..64 : "middle aged"
  when > 65 : "senior"
  else : "not an age"
end

(please don't anybody be offended by my age categories, i just made up
this example off the top of my head)

Anyway, the above doesn't work - syntax error.
Neither does this:

when age < 12 : "child"

the test doesn't pass, so if age is eg 10, i get nil back.

Can someone set me straight?
thanks
max

···

*******************************
postscript - it seems the word 'ad*lt* triggers the spam filter. hence
the odd wording above.
--
Posted via http://www.ruby-forum.com/.

Max Williams wrote:

In a case statement, i know how to use ranges to compare against the
given variable. But how do i use < or > ?

Simplest solution is to use a Range with extreme bounds, or use an if
statement (if age < 25 ...).

The long answer is to explain that

  case foo
  when bar
    ...
  end

is syntactic sugar for

  if bar === foo
    ...
  end

So you can get whatever behaviour you like by creating an object which
responds to the === method.

class Bounds
  def initialize(meth,val)
    @meth, @val = meth, val
  end
  def ===(other)
    other.send(@meth, @val)
  end
end
def is(meth,val)
  Bounds.new(meth,val)
end

age = 70
case age
when is(:<,25)
  puts "Youngster"
when is(:>,65)
  puts "Oldie"
end

If you wanted this to be more efficient, you could define constants like

UNDER_25 = is(:<,25)
OVER_65 = is(:>,65)

case age
when UNDER_25
  ... etc
end

···

--
Posted via http://www.ruby-forum.com/\.

As the others pointed out, there's no easy way to do what you want to.
On the other hand, if you know the bounds of your inputs, your method
isn't bad ; I'd write :

category = case age
  when 0...12 then "child"
  when 12...18 then "minor"
  when 18...25 then "young ad*lt"
  when 25...50 then "ad*lt"
  when 50...65 then "middle aged"
  when 65...999 then "senior"
  else "not an age"
end

Note that the use of : within if's and case's has been deprecated in
Ruby 1.9 and the next versions.

Fred

···

Le 2 juin 2009 à 11:12, Max Williams a écrit :

category = case age
  when < 12 : "child"
  when 13..17 : "minor"
  when 18..24 : "young ad*lt"
  when 25..49 : "ad*lt"
  when 50..64 : "middle aged"
  when > 65 : "senior"
  else : "not an age"
end

--
Home, home again I like to be here when I can
When I come home cold and tired
It's good to warm my bones besides the fire
                                           (Pink Floyd, Breathe Reprise)

I've attached a similar but more general approach - and a few others as well.

Kind regards

robert

cond.rb (1.24 KB)

···

2009/6/2 Brian Candler <b.candler@pobox.com>:

Max Williams wrote:

In a case statement, i know how to use ranges to compare against the
given variable. But how do i use < or > ?

So you can get whatever behaviour you like by creating an object which
responds to the === method.

class Bounds
def initialize(meth,val)
@meth, @val = meth, val
end
def ===(other)
other.send(@meth, @val)
end
end
def is(meth,val)
Bounds.new(meth,val)
end

age = 70
case age
when is(:<,25)
puts "Youngster"
when is(:>,65)
puts "Oldie"
end

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Wow, that's a lot more complicated than i thought. I think for the sake
of ease and readability i'd stick with doing a more longwinded version,
like

category = case
  when age < 12 : "child"
  when (13..17).include? age : "minor"
  when (18..24).include? age : "young ad*lt"
  when (25..49).include? age : "ad*lt"
  when (50..64).include? age : "middle aged"
  when age > 65 : "senior"
  else : "not an age"
end

thanks for the insight though!

cheers
max

···

--
Posted via http://www.ruby-forum.com/.

Brian Candler wrote:

Simplest solution is to use a Range with extreme bounds,

... such as a range that ends in Infinity:

65..(1/0.0)
=> 65..Infinity

:wink:

Clifford Heath.

thanks for your in-depth answer robert! i'll chew over that. but, in
terms of readability, i think my solution of not passing age into the
block and instead testing it on every line is fine.

thanks a lot though.
max

···

--
Posted via http://www.ruby-forum.com/.

Max Williams wrote:

Wow, that's a lot more complicated than i thought. I think for the sake
of ease and readability i'd stick with doing a more longwinded version,
like

category = case
  when age < 12 : "child"
  when (13..17).include? age : "minor"
  when (18..24).include? age : "young ad*lt"
  when (25..49).include? age : "ad*lt"
  when (50..64).include? age : "middle aged"
  when age > 65 : "senior"
  else : "not an age"
end

thanks for the insight though!

If you want to allow for the possibility of fractional ages:

  when (13...18).include? age
  when (18...25).include? age
  when (18...50).include? age
  .. etc

···

--
Posted via http://www.ruby-forum.com/\.

Clifford Heath wrote:

Brian Candler wrote:

Simplest solution is to use a Range with extreme bounds,

... such as a range that ends in Infinity:

65..(1/0.0)
=> 65..Infinity

:wink:

Clifford Heath.

haha, i thought about that but it seemed kind of crazy. It surprises me
a little that Infinity isn't a singleton class like NilClass in ruby.

···

--
Posted via http://www.ruby-forum.com/\.

Good point, thanks :slight_smile: i guess you meant (25..50) for the last one :slight_smile:

cheers!
max

···

--
Posted via http://www.ruby-forum.com/.

Brian Candler wrote:

65..(1/0.0)
=> 65..Infinity

haha, i thought about that but it seemed kind of crazy. It surprises me
a little that Infinity isn't a singleton class like NilClass in ruby.

···

--
Posted via http://www.ruby-forum.com/\.

I guess that is because there are actually 2 infinities and both are valid
values with well-defined operations in IEEE754.

Regards,
Florian

···

On Jun 2, 2009, at 3:32 PM, Max Williams wrote:

Clifford Heath wrote:

Brian Candler wrote:

Simplest solution is to use a Range with extreme bounds,

... such as a range that ends in Infinity:

65..(1/0.0)
=> 65..Infinity

:wink:

Clifford Heath.

haha, i thought about that but it seemed kind of crazy. It surprises me
a little that Infinity isn't a singleton class like NilClass in ruby.

--
Florian Gilcher

smtp: flo@andersground.net
jabber: Skade@jabber.ccc.de
gpg: 533148E2

Interesting... you can assign it to a constant.

Infinity = 1/0.0

Then you can use it in ranges:

(-Infinity..0).include? 100000
=> false
(0..Infinity).include? 100000
=> true

···

On Jun 2, 9:32 am, Max Williams <toastkid.willi...@gmail.com> wrote:

Clifford Heath wrote:
> Brian Candler wrote:
>> Simplest solution is to use a Range with extreme bounds,

> ... such as a range that ends in Infinity:

> 65..(1/0.0)
> => 65..Infinity

Max Williams wrote:

Good point, thanks :slight_smile: i guess you meant (25..50) for the last one :slight_smile:

Yeah, you can tell I copy-pasted it from the line above :slight_smile:

···

--
Posted via http://www.ruby-forum.com/\.

That's an interesting idea.. I can see an opportunity for a great deal of
abuse there, as well.
It would certainly be cool to write my infinite loops like:

(0..Infinity).each {|d| ... }

Alex

···

On Tue, Jun 2, 2009 at 3:21 PM, Mark Thomas <mark@thomaszone.com> wrote:

On Jun 2, 9:32 am, Max Williams <toastkid.willi...@gmail.com> wrote:
> Clifford Heath wrote:
> > Brian Candler wrote:
> >> Simplest solution is to use a Range with extreme bounds,
>
> > ... such as a range that ends in Infinity:
>
> > 65..(1/0.0)
> > => 65..Infinity

Interesting... you can assign it to a constant.

Infinity = 1/0.0

Then you can use it in ranges:

(-Infinity..0).include? 100000
=> false
(0..Infinity).include? 100000
=> true

By the way, this is a real good way to lock up your cpu, i just
discovered :slight_smile:

infinity = 1.0/0
(0..infinity).to_a

grrrrrrriiiiiiinnnnnnnddddddddd

···

--
Posted via http://www.ruby-forum.com/.