Case Expression Different in Ruby 1.9

Case expression different in Ruby 1.9?

There was a change in the syntax between 1.8.x and 1.9.x where the : is now no longer allowed:

 birthyear = 1986
generation = case birthyear
when 1946...1963
"Baby boomer"
when 1964...1976
"Generation X"
when 1977...2012
"new generation"
else
nil
end

puts generation

Technically : has been replaced by then but that's an optional keyword if you use a newline. It's a bit of a hassle to go and track down cases where you've used the old syntax, so hopefully searching for case is close enough.

Difference between == and case?

It looks like a bug in YARV on windows. I get the correct output in JRuby 1.6.0:

# ruby -v
ruby 1.9.2p180 (2011-02-18) [i386-mingw32]

# ruby test.rb
Quote
ErrCase
true
true
"\""

# jruby --1.9 -v
jruby 1.6.0 (ruby 1.9.2 patchlevel 136) (2011-03-15 f3b6154) (Java HotSpot(TM) Client VM 1.7.0-ea) [Windows XP-x86-java]

# jruby --1.9 test.rb
Quote
QuoteCase
true
true
"\""

How to do multiple assignment with return values in ruby (1.9) case statement?

You should be returning array for this. Otherwise it confuses the parser.

limit, pattern = case period_group
when 'day' then [7, 'D']
when 'week' then [7, 'WW']
else ['12','MM']
end

I don't see why you wanted to get rid of square brackets. It's even more readable that way.

Ruby: target-less 'case', compared to 'if'

Midwire ran a few benchmarks and concluded that if/elsif is faster
than case because case “implicitly compares using the more expensive
=== operator”.

Here is where I got this quote. It compares if/elsif statements to case.

It is very thorough and explores the differences in the instruction sequence, definitely will give you an idea on which is better.

The main thing i pulled from the post though, is that both if/else if and case have no huge differences, both can usually be used interchangeably.

Some major differences can present themselves depending on how many cases you have.

n = 1 (last clause matches)
if: 7.4821e-07
threequal_if: 1.6830500000000001e-06
case: 3.9176999999999997e-07

n = 15 (first clause matches)
if: 3.7357000000000003e-07
threequal_if: 5.0263e-07
case: 4.3348e-07

As you can see, if the last clause is matched,if/elsif runs much slower than case, while if the first clause is matched, it's the other way around.

This difference comes from the fact that if/elsif uses branchunless, while case uses branchif in their instruction sequences.


Here is a test I did on my own with a target-less case vs if/elsif statements (using "=="). The first time is case, while the second time is if/elsif.

First test, 5 when statements, 5 if/elsif, the first clause is true for both.

Time elapsed 0.052023 milliseconds                                                                                                                                                                                                                                                                                                                                                                                                       
Time elapsed 0.031467999999999996 milliseconds

Second test, 5 when statements, 5 if/elsif, the last(5th) clause is true for both.

Time elapsed 0.001224 milliseconds                                                                                                                                                                                                                                                                                                                                                                                                 
Time elapsed 0.028578 milliseconds

As you can see, just as we saw before, when the first clause is true, if/elsif perform better than case, while case has a massive performance advantage when the last clause is true.

CONCLUSION

Running more tests has shown that it probably comes down to probability. If you think the answer is going to come earlier in your list of clauses, use if/elsif, otherwise case seems to be faster.

The main thing that this has shown is that both case and if/elsif are equally efficient and that using one over the other comes down to probability and taste.

SyntaxError using Case Expression on Sinatra 1.2.0 and Ruby 1.9.2

The problem is that you can't have arbitrary statements in a case statement. This is actually a very rare case where ruby limits where you can have code.

The way ERb works is that it inserts statements around your code to which it channels the output. You can see it in your error log. In this case the code that is generated is something like this:

case @status
@_out_buf.concat "\n "
when "foo"
@_out_buf.concat "\n It's a FOO!\n "
when "bar"
@_out_buf.concat "\n It's a BAR!\n "
else
@_out_buf.concat "\n It's something else...!\n "
end

As you see the second line here is what causes the problem. You might be able to solve it is have your ERb suppress the newline concat:

<% case @status; when "foo" %>

or (though this might not work):

 <% case @status -%>
<% when "foo" %>

How to write a switch statement in Ruby

Ruby uses the case expression instead.

case x
when 1..5
"It's between 1 and 5"
when 6
"It's 6"
when "foo", "bar"
"It's either foo or bar"
when String
"You passed a string"
else
"You gave me #{x} -- I have no idea what to do with that."
end

Ruby compares the object in the when clause with the object in the case clause using the === operator. For example, 1..5 === x, and not x === 1..5.

This allows for sophisticated when clauses as seen above. Ranges, classes and all sorts of things can be tested for rather than just equality.

Unlike switch statements in many other languages, Ruby’s case does not have fall-through, so there is no need to end each when with a break. You can also specify multiple matches in a single when clause like when "foo", "bar".

How does Ruby 1.9 handle character cases in source code?

I can't get IRB to accept UTF-8 characters, so I used a test script (/tmp/utf_test.rb).

"λ" works fine as a variable name:

# encoding: UTF-8
λ = 'foo'
puts λ

# from the command line:
> ruby -KU /tmp/utf_test.rb
foo

"λ" also works fine as a method name:

# encoding: UTF-8
Kernel.class_eval do
alias_method :λ, :lambda
end

(λ { puts 'hi' }).call

# from the command line:
> ruby -KU /tmp/utf_test.rb:
hi

It doesn't work as a constant, though:

# encoding: UTF-8
Object.const_set :λ, 'bar'

# from the command line:
> ruby -KU /tmp/utf_test.rb:
utf_test.rb:2:in `const_set': wrong constant name λ (NameError)

Nor does the capitalized version:

# encoding: UTF-8
Object.const_set :Λ, 'bar'

# from the command line:
> ruby -KU /tmp/utf_test.rb:
utf_test.rb:2:in `const_set': wrong constant name Λ (NameError)

My suspicion is that constant names must start with a capital ASCII letter (must match /^[A-Z]/).

Why doesn't case with when 2 work?

An if statement would probably be more fitting for your code, since you don't have a definitive range/value, but rather just a greater-than:

if ARGV.length == 0
abort "Error 1"
elsif ARGV.length > 2
abort "Error 2"
end

Ruby 1.9: how can I properly upcase & downcase multibyte strings?

Case conversion is locale dependent and doesn't always round-trip, which is why Ruby 1.9 doesn't cover it (see here and here)

The unicode-util gem should address your needs.



Related Topics



Leave a reply



Submit