In a recent project, I wrote a standard case
statement which runs a conditional based on the outcome of performing a numeric operation on a value.
A sample of the code is as follows:
1
2
3
4
5
6
n = 2
case n
when (n % 2 ==0) then "even"
else puts "odd"
end
In theory, the output should be even
given that n is divisible by 2. However, the above will output odd
despite what the value of n
is. This is due to the way when
works in a case statement.
From the above example, the when
statement is translated as:
1
(n % 2 == 0) === n # => false
which will always return false, hence printing odd
no matter what variable n holds.
The only way to handle numeric operations in Ruby case statements is to encapsulate it inside a proc and use that in the when
statement. Rewriting the above:
1
2
3
4
5
6
7
8
9
10
even = ->(x){ x % 2 == 0 }
n = 2
res = case n
when even "even"
else "odd"
end
res # => "even"
This works because underneath the hood, proc aliases the threequals ===
operator to the call
method. It is important to realise that the ===
operator is a method
and should not be treated as an equality operation.
This has actually caused me some confusion and led to some debugging. I hope it helps someone with a similar issue.
Stay curious and keep hacking!