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"
.
case...when
behaves a bit unexpectedly when handling classes. This is due to the fact that it uses the ===
operator.
That operator works as expected with literals, but not with classes:
1 === 1 # => true
Fixnum === Fixnum # => false
This means that if you want to do a case ... when
over an object's class, this will not work:
obj = 'hello'
case obj.class
when String
print('It is a string')
when Fixnum
print('It is a number')
else
print('It is not a string or number')
end
Will print "It is not a string or number".
Fortunately, this is easily solved. The ===
operator has been defined so that it returns true
if you use it with a class and supply an instance of that class as the second operand:
Fixnum === 1 # => true
In short, the code above can be fixed by removing the .class
from case obj.class
:
obj = 'hello'
case obj # was case obj.class
when String
print('It is a string')
when Fixnum
print('It is a number')
else
print('It is not a string or number')
end
I hit this problem today while looking for an answer, and this was the first appearing page, so I figured it would be useful to others in my same situation.
It is done using case
in Ruby. Also see "Switch statement" on Wikipedia.
Quoted:
case n
when 0
puts 'You typed zero'
when 1, 9
puts 'n is a perfect square'
when 2
puts 'n is a prime number'
puts 'n is an even number'
when 3, 5, 7
puts 'n is a prime number'
when 4, 6, 8
puts 'n is an even number'
else
puts 'Only single-digit numbers are allowed'
end
Another example:
score = 70
result = case score
when 0..40 then "Fail"
when 41..60 then "Pass"
when 61..70 then "Pass with Merit"
when 71..100 then "Pass with Distinction"
else "Invalid Score"
end
puts result
On around page 123 of The Ruby Programming Language (1st Edition, O'Reilly) on my Kindle, it says the then
keyword following the when
clauses can be replaced with a newline or semicolon (just like in the if then else
syntax). (Ruby 1.8 also allows a colon in place of then
, but this syntax is no longer allowed in Ruby 1.9.)