I was playing today and accidentally end up writting this, now I'm courious.
i = 101
case i
when 1..100
puts " will never happen "
when i == 101
puts " this will not appear "
else
puts " this will appear"
end
How ruby internally process when i == 101 is like i == (i == 101) ?
Your code is equivalent to:
if (1..100) === 101
puts " will never happen "
elsif (101 == 101) === 101
puts " this will not appear "
else
puts " this will appear"
end
If we look at Range#=== we see that
(1..100) === 101
is equivalent to:
(1..100).include?(101)
#=> false
(101 == 101) === 101 reduces to:
true === 101
We see from the doc for TrueClass#=== that this is equivalent to:
true == 101
#=> false
Hence, the else clause is executed.
The structure
case a
when x
code_x
when y
code_y
else
code_z
end
evaluates identically to
if x === a
code_x
elsif y === a
code_y
else
code_z
end
Each when calls the method === on the argument of when, passing the argument of case as the parameter (x === a is identical to x.===(a)). The === method is slightly different than ==: it is typically called "case subsumption". For simple types like numbers and strings, it is the same thing as ==. For Range and Array objects, it is a synonym for .include?. For Regexp objects, it is quite similar to match. For Module objects, it tests whether the argument is an instance of that module or one of its descendants (basically, if x === a then a.instance_of?(x)). Thus, in your code,
if (1..101) === i
...
elsif (i == 101) === i
...
else
...
end
which performs pretty much the same tests as
if (1..101).include?(i)
...
elsif (i == 101) == i
...
else
...
end
Note that there is another form of case that does not employ ===:
case
when x
code_x
when y
code_y
else
code_z
end
which is identical to
if x
code_x
elsif y
code_y
else
code_z
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With