Two identical when clauses in one case
Question
What's the return value of the following Ruby code?
a = [1, 2]
res = []
case a.size
when 2 then res << 1
when 2 then res << 2
end
res # => ???
The correct answer is
-
[2] -
[1]Correct -
[2, 1] -
[1, 2]
Explanation
TL;DR
A case statement tests its when clauses top to bottom and executes only the first one that matches, then exits. a.size is 2, the first when 2 matches and appends 1, and the second when 2 is never reached. res is [1].
Step by step
a = [1, 2]
res = []
case a.size
when 2 then res << 1
when 2 then res << 2
end
res # => [1]
There is no fall-through in Ruby's case. Unlike a C switch, a matching branch does not continue into the next one, and no break is needed. A second clause with the same condition is simply dead code.
Under the hood
Each when tests its candidate against the case value with the case equality operator ===, in source order. The snippet is equivalent to:
a = [1, 2]
res = []
if 2 === a.size
res << 1
elsif 2 === a.size
res << 2
end
res # => [1]
Once the if branch matches, the elsif condition is never evaluated. Ruby knows the duplicated clause is unreachable: run the original snippet with warnings enabled (ruby -w) and it prints a warning that the second when clause duplicates the first and is ignored.
Edge cases
To run one branch for several values, list them in a single when instead of repeating clauses:
result =
case [1, 2].size
when 2, 3 then :few
else :many
end
result # => :few
case is an expression: it returns the value of the branch that ran. When nothing matches and there is no else, it returns nil:
result =
case 5
when 2 then :two
end
result # => nil
Share this quiz
Comments
No comments yet. Be the first.