[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Ruby's "case" doesn't behave like a normal switch

Guillaume Nargeot

2/23/2007 1:54:00 AM

The problem with ruby is that you can't use a switch as it behaves with many
other languages like C, php, etc.

For example, you want to convert the following peace of code to ruby:

switch (x) {
case 1:
case 2:
# do something
break;
case 3:
# do some other thing
break;
default:
}

it seems you can do it with the following code:

case x
when 1..2
# do something
when 3
# do some other thing
else
end

But when it comes to strings, you would like to be able to do simply:

case x
when "this"
when "that"
# do something common to "this" and "that"
when "nothing"
# something different
end

The problem is that you can't, because of the fact the "break" is implicit
in
the ruby language.
The fact is that you don't want to rewrite the same code two times.
Of course, you would be able to right your code into a function, and then
just
write:

case x
when "this"
func_this_that()
when "that"
func_this_that()
when "nothing"
# something different
end

But if again, you don't want to relay on a function call, here's a solution
I thought about.

This is not perfect, because you have to change your syntax, but it might be
quite useful in some cases.

# Redefine the === method of the Array class, that is used to match the
argument
# of the "case" directive.
class Array
# Return true if self contains any element of the given parameter.
def ===(o)
o.each do |e|
return true if self.include?(e)
end
false
end
end

# Example 1
x = ["case4"]

case x
when ["case1", "case2"]
puts "first case"
when ["case3", "case4", "case5"]
puts "second case"
when ["case6"]
puts "third case"
else
puts "not matched"
end

# Returns: "second case"

# Example 2
x = [6]

case x
when [1, 2]
puts "first case"
when [3, 4, 5]
puts "second case"
when [6]
puts "third case"
else
puts "not matched"
end

# Returns: "third case"

What do you think about it ?
16 Answers

WATANABE Hirofumi

2/23/2007 2:14:00 AM

0

Hi,

On Fri, Feb 23, 2007 at 10:55:06AM +0900,
Guillaume Nargeot wrote:

> The fact is that you don't want to rewrite the same code two times.
> Of course, you would be able to right your code into a function, and then
> just
> write:
>
> case x
> when "this"
> func_this_that()
> when "that"
> func_this_that()
> when "nothing"
> # something different
> end

case x
when "this", "that"
func_this_that()
when "nothing"
# something different
end

--
eban

Kjell Olsen

2/23/2007 2:23:00 AM

0

Check this out for making your case statements work:

http://redhanded.hobix.com/bits/wonderOfTheWhenB...

"Consider Olympic ice dancing out-graced!"

-kjell

On Feb 22, 2007, at 7:55 PM, Guillaume Nargeot wrote:

> The problem with ruby is that you can't use a switch as it behaves
> with many
> other languages like C, php, etc.
>
> For example, you want to convert the following peace of code to ruby:
>
> switch (x) {
> case 1:
> case 2:
> # do something
> break;
> case 3:
> # do some other thing
> break;
> default:
> }
>
> it seems you can do it with the following code:
>
> case x
> when 1..2
> # do something
> when 3
> # do some other thing
> else
> end
>
> But when it comes to strings, you would like to be able to do simply:
>
> case x
> when "this"
> when "that"
> # do something common to "this" and "that"
> when "nothing"
> # something different
> end
>
> The problem is that you can't, because of the fact the "break" is
> implicit
> in
> the ruby language.
> The fact is that you don't want to rewrite the same code two times.
> Of course, you would be able to right your code into a function,
> and then
> just
> write:
>
> case x
> when "this"
> func_this_that()
> when "that"
> func_this_that()
> when "nothing"
> # something different
> end
>
> But if again, you don't want to relay on a function call, here's a
> solution
> I thought about.
>
> This is not perfect, because you have to change your syntax, but it
> might be
> quite useful in some cases.
>
> # Redefine the === method of the Array class, that is used to match
> the
> argument
> # of the "case" directive.
> class Array
> # Return true if self contains any element of the given parameter.
> def ===(o)
> o.each do |e|
> return true if self.include?(e)
> end
> false
> end
> end
>
> # Example 1
> x = ["case4"]
>
> case x
> when ["case1", "case2"]
> puts "first case"
> when ["case3", "case4", "case5"]
> puts "second case"
> when ["case6"]
> puts "third case"
> else
> puts "not matched"
> end
>
> # Returns: "second case"
>
> # Example 2
> x = [6]
>
> case x
> when [1, 2]
> puts "first case"
> when [3, 4, 5]
> puts "second case"
> when [6]
> puts "third case"
> else
> puts "not matched"
> end
>
> # Returns: "third case"
>
> What do you think about it ?
>


Chad Perrin

2/23/2007 3:23:00 AM

0

On Fri, Feb 23, 2007 at 10:55:06AM +0900, Guillaume Nargeot wrote:
>
> it seems you can do it with the following code:
>
> case x
> when 1..2
> # do something
> when 3
> # do some other thing
> else
> end
>
> But when it comes to strings, you would like to be able to do simply:
>
> case x
> when "this"
> when "that"
> # do something common to "this" and "that"
> when "nothing"
> # something different
> end

These two examples are not equivalent. In one, you're listing multiple
cases on a single line with the associated code following it. In the
other, you're listing cases separately and letting the lack of a break
cause it to fail over to the next -- which leads to a very unintuitive
set of code. Why not just employ your list of cases for the same
resulting code on one line? That works just fine.

--
CCD CopyWrite Chad Perrin [ http://ccd.ap... ]
"The ability to quote is a serviceable
substitute for wit." - W. Somerset Maugham

dblack

2/23/2007 4:23:00 AM

0

Florian Frank

2/23/2007 4:42:00 AM

0

Guillaume Nargeot wrote:
> # Example 1
> x = ["case4"]
>
> case x
> when ["case1", "case2"]
> puts "first case"
> when ["case3", "case4", "case5"]
> puts "second case"
> when ["case6"]
> puts "third case"
> else
> puts "not matched"
> end
>
> # Returns: "second case"
>
> # Example 2
> x = [6]
>
> case x
> when [1, 2]
> puts "first case"
> when [3, 4, 5]
> puts "second case"
> when [6]
> puts "third case"
> else
> puts "not matched"
> end
>
> # Returns: "third case"
>
> What do you think about it ?
>
You can already do this:

a = [3, 4, 5]
case x
when 1, 2
puts "first case"
when *a
puts "second case"
when 6
puts "third case"
else
puts "not matched"
end

There are cases of C's fall-through switch, that cannot be emulated by Ruby's case - and I think that's a good thing. To make breaks necessary to break out of a case clause (and creating the danger for programmers to incidentally forget one), was probably one of the most inane ideas of the C language's creators.

--
Florian Frank


Guillaume Nargeot

2/23/2007 5:00:00 AM

0

> case x
> when "this", "that"
> func_this_that()
> when "nothing"
> # something different
> end

Thank you very much !!!
I thought I tested everything, but obviously not this one.
I didn't even find anything about it in the official documentation.

So, thank you again, that is exactely what I needed ;)

Brian Candler

2/23/2007 10:31:00 AM

0

On Fri, Feb 23, 2007 at 02:05:10PM +0900, Guillaume Nargeot wrote:
> > case x
> > when "this", "that"
> > func_this_that()
> > when "nothing"
> > # something different
> > end
>
> Thank you very much !!!
> I thought I tested everything, but obviously not this one.
> I didn't even find anything about it in the official documentation.

http://www.rubycentral.com/book/tut_expres...
Search down to the section headed "Case Expressions"

Olivier

2/23/2007 1:19:00 PM

0

Le vendredi 23 février 2007 11:30, Brian Candler a écrit :
> On Fri, Feb 23, 2007 at 02:05:10PM +0900, Guillaume Nargeot wrote:
> > > case x
> > > when "this", "that"
> > > func_this_that()
> > > when "nothing"
> > > # something different
> > > end
> >
> > Thank you very much !!!
> > I thought I tested everything, but obviously not this one.
> > I didn't even find anything about it in the official documentation.
>
> http://www.rubycentral.com/book/tut_expres...
> Search down to the section headed "Case Expressions"

I didn't know about this syntax, either. Thanks, Eban ! For the Strings, I
thought about using Regex, instead :

case x
when /this|that/
func_this_that()
when "nothing"
# something different
end

--
Olivier Renaud

Brian Candler

2/23/2007 3:26:00 PM

0

On Fri, Feb 23, 2007 at 10:18:34PM +0900, Olivier Renaud wrote:
> Le vendredi 23 février 2007 11:30, Brian Candler a écrit :
> > On Fri, Feb 23, 2007 at 02:05:10PM +0900, Guillaume Nargeot wrote:
> > > > case x
> > > > when "this", "that"
> > > > func_this_that()
> > > > when "nothing"
> > > > # something different
> > > > end
> > >
> > > Thank you very much !!!
> > > I thought I tested everything, but obviously not this one.
> > > I didn't even find anything about it in the official documentation.
> >
> > http://www.rubycentral.com/book/tut_expres...
> > Search down to the section headed "Case Expressions"
>
> I didn't know about this syntax, either. Thanks, Eban ! For the Strings, I
> thought about using Regex, instead :
>
> case x
> when /this|that/
> func_this_that()
> when "nothing"
> # something different
> end

That's not the same though. I think you'd need:

when /\A(this|that)\z/

(which is a gotcha if you come from Perl, and expect to use ^...$ to match
the start and end of the string)

Regards,

Brian.

gga

2/23/2007 6:19:00 PM

0

On 22 Feb., 22:54, Guillaume Nargeot
<guillaume.nargeotDONOTFUCKINGS...@fusionsystems.co.jp> wrote:
> The problem with ruby is that you can't use a switch as it behaves with many
> other languages like C, php, etc.
>
> For example, you want to convert the following peace of code to ruby:
>
> switch (x) {
> case 1:
> case 2:
> # do something
> break;
> case 3:
> # do some other thing
> break;
> default:
>
> }

For completeness sake, you can also emulate C's lack of a break;
statement in ruby by doing redo/retry, like:


a = 1

catch(:redo) do
case a
when 1
print '1'
a = 2
redo
when 2
puts 'and 2'
end
end


This makes ruby's case statement probably the best of any language.