Case statement and ranges

Hey, I want to do something like that:

case amount
when 25..50: 42
when 51..66: 78
when 90..123: 99
end

which works of course.

Now what I would like to have some other cases like when amount is lower
that 25, but with no minimum, or when it is higher that 123 ...
I could write something like:

case
when amount === (25..50): 42
when amount === (51..66): 78
when amount === (90..123): 99
when amount < 25: 100
when amount > 123: 200
else 0 # this would happen only when amount is in 67...90
end

But it doesn't feel that well ... since I am repeating my amount
variable all the time and this is precisely what the 'case something'
construct is about.

I cold also use some extremely high and extremely low values in ranges,
like (123..100000000) or (-10000000..25) to handle the other cases since
I know that in my use, it would be fine. But it does look quite
inelegant ....

thx

···

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

the basis of a solution:

cfp:~ > cat a.rb

case 42
   when all(:a, :b, :c)
     puts 'nope'

   when any(42, 43, 44)
     puts 'forty-two'
end

case 42
   when any
     puts 42
end

case 42.0
   when any( 25 .. 50, any )
     p 42.0
   when 51 .. 66
   when 90 .. 123
end

case 4.2
   when any( 25 .. 50, any )
     p 4.2
   when 51 .. 66
   when 90 .. 123
end

BEGIN {

   class Pattern < ::Array
     def initialize *elements
       replace elements unless elements.empty?
     end

     def inspect
       "#{ self.class.name }#{ super }"
     end

     class Any < Pattern
       def === other
         return true if empty?
         any?{|element| element === other}
       end
       alias_method '==', '==='
     end

     class All < Pattern
       def === other
         return false if empty?
         all?{|element| element === other}
       end
       alias_method '==', '==='
     end
   end

   def all(*a, &b) Pattern::All.new(*a, &b) end
   def any(*a, &b) Pattern::Any.new(*a, &b) end

}

cfp:~ > ruby a.rb
forty-two
42
42.0
4.2

a @ http://codeforpeople.com/

···

On Aug 13, 2008, at 4:21 PM, Mini Skirt wrote:

Hey, I want to do something like that:

case amount
when 25..50: 42
when 51..66: 78
when 90..123: 99
end

which works of course.

Now what I would like to have some other cases like when amount is lower
that 25, but with no minimum, or when it is higher that 123 ...
I could write something like:

--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama

If you use version 0.5 my 'case' gem:

require 'rubygems'
require 'case'

case amount
when (25..50): 42
when (51..66): 78
when (90..123): 99
when (Case::Cmp < 25): 100
when (Case::Cmp > 123): 200
else 0
end

-mental

···

On Thu, 2008-08-14 at 07:21 +0900, Mini Skirt wrote:

Now what I would like to have some other cases like when amount is lower
that 25, but with no minimum, or when it is higher that 123 ...
I could write something like:

case
when amount === (25..50): 42
when amount === (51..66): 78
when amount === (90..123): 99
when amount < 25: 100
when amount > 123: 200
else 0 # this would happen only when amount is in 67...90
end

I agree that your second example doesn't feel right... I prefer altering your original example:

case amount
when 25..50: 42
when 51..66: 78
when 90..123: 99
else amount < 25 ? 100 : 200
end

Mini Skirt wrote:

Hey, I want to do something like that:

case amount
when 25..50: 42
when 51..66: 78
when 90..123: 99
end

which works of course.

Now what I would like to have some other cases like when amount is lower
that 25, but with no minimum, or when it is higher that 123 ...
I could write something like:

case
when amount === (25..50): 42
when amount === (51..66): 78
when amount === (90..123): 99
when amount < 25: 100
when amount > 123: 200
else 0 # this would happen only when amount is in 67...90
end

But it doesn't feel that well ... since I am repeating my amount
variable all the time and this is precisely what the 'case something'
construct is about.

I cold also use some extremely high and extremely low values in ranges,
like (123..100000000) or (-10000000..25) to handle the other cases since
I know that in my use, it would be fine. But it does look quite
inelegant ....

thx

Big numbers are more elegant if they are big enough:

Infinity = 1/0.0
amount = 456
p case amount
when 25..50: 42
when 51..66: 78
when 90..123: 99
when -Infinity..25: 100
when 123..Infinity: 200
end

···

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Don't use this; it's just for fun...

my_number = 57
begin
  [25, 51, 67, 90, 123].zip([100, 42, 78, 0, 99]).select {|a| a[1] if
my_number < a[0]}.first[1] rescue 200
end

Two things.

1. It's generally not good form to use a rescue for program logic

2. I'm surprised that no one saw the fundamental problem in using
ranges. We're looking at a line that has divisions, not pieces that
may or may not overlap. I suppose if you were clever, you could make
it work and have it behave almost the way you want it to.

I'd go with dividers instead of ranges. You could build your ranges
automagically with a list of the divisions, I suppose.

Even though at first glance it seems verbose, I do like Ara's
solution. And Ryan Davis' crack is really simple and succinct. Like
them both!

Todd

···

On Wed, Aug 13, 2008 at 6:59 PM, Ryan Davis <ryand-ruby@zenspider.com> wrote:

I agree that your second example doesn't feel right... I prefer altering
your original example:

case amount
when 25..50: 42
when 51..66: 78
when 90..123: 99
else amount < 25 ? 100 : 200
end

I always throw this in my core_ext:

···

class Float
  Infinity = 1.0/0.0
end

On Aug 13, 2008, at 6:26 PM, Joel VanderWerf wrote:

Mini Skirt wrote:

Hey, I want to do something like that:
case amount
when 25..50: 42
when 51..66: 78
when 90..123: 99
end
which works of course.
Now what I would like to have some other cases like when amount is lower
that 25, but with no minimum, or when it is higher that 123 ...
I could write something like:
case
when amount === (25..50): 42
when amount === (51..66): 78
when amount === (90..123): 99
when amount < 25: 100
when amount > 123: 200
else 0 # this would happen only when amount is in 67...90
end
But it doesn't feel that well ... since I am repeating my amount
variable all the time and this is precisely what the 'case something'
construct is about.
I cold also use some extremely high and extremely low values in ranges,
like (123..100000000) or (-10000000..25) to handle the other cases since
I know that in my use, it would be fine. But it does look quite
inelegant ....
thx

Big numbers are more elegant if they are big enough:

Infinity = 1/0.0
amount = 456
p case amount
when 25..50: 42
when 51..66: 78
when 90..123: 99
when -Infinity..25: 100
when 123..Infinity: 200
end

--
     vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

elliottcable wrote:

I always throw this in my core_ext:

class Float
  Infinity = 1.0/0.0
end

If it goes in core it should really be

Infinity = 42/0.0

:slight_smile:

···

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Infinity + Infinity
=> Infinity
Infinity - Infinity
=> NaN
Infinity + Infinity - Infinity
=> Nan

Todd

Todd

···

On Wed, Aug 13, 2008 at 9:34 PM, Joel VanderWerf <vjoel@path.berkeley.edu> wrote:

elliottcable wrote:

I always throw this in my core_ext:

class Float
Infinity = 1.0/0.0
end

If it goes in core it should really be

Infinity = 42/0.0

:slight_smile:

Infinity = 42/0.0
UniverseError: ‽‽‽
  from (irb):2

Infinity = 42/0.0

···

On Aug 13, 2008, at 6:34 PM, Joel VanderWerf wrote:

Todd Benson wrote:

Infinity + Infinity
=> Infinity
Infinity - Infinity
=> NaN
Infinity + Infinity - Infinity
=> Nan

That seems right, or at least that's what I get counting on my fingers.

···

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407