this code doesn’t compile.
ch = nil
case ch
when 'A' .. 'Z'
puts "ch is capital"
when Nil
puts "ch is nil"
end
In case statement, if no range expression, it is compiled successfully.
this code doesn’t compile.
ch = nil
case ch
when 'A' .. 'Z'
puts "ch is capital"
when Nil
puts "ch is nil"
end
In case statement, if no range expression, it is compiled successfully.
Put the when Nil
first, would be the easiest way to fix this.
It’s a bug, please report it. Thank you!
Following code still not work on 1.7.2, any one report bug on this?
ch : Char? = nil
case ch
when 'A'..'Z'
puts "ch is capital"
when Nil
puts "ch is nil"
end
In 1.cr:13:6
13 | when 'A'..'Z'
^-
Error: instantiating 'Range(Char, Char)#===(Nil)'
In /home/zw963/Crystal/share/crystal/src/range.cr:327:5
327 | includes?(value)
^--------
Error: instantiating 'includes?(Nil)'
In /home/zw963/Crystal/share/crystal/src/range.cr:298:32
298 | (begin_value.nil? || value >= begin_value) &&
^
Error: undefined method '>=' for Nil
Nil trace:
/home/zw963/Crystal/share/crystal/src/range.cr:298
(begin_value.nil? || value >= begin_value) &&
/home/zw963/Crystal/share/crystal/src/range.cr:293
def includes?(value) : Bool
because it is not really a bug.
the switch case ...
block is translated to a series of if ... then ... elsif ... then ...
.
another feature of crystal is can predict what a variable is null or not, by using if
guard.
So if you put when Nil
first if will be translated to:
if ch.is_a?(Nil)
...
else # we know that ch is not nil, thus `Char` here
....
I guess the compiler can be a little smarter to always put Nil on top of the expanded expression, but this is unexpected and can create subtle bugs for someone who expect the conditions match sequentially.
So unless we can make sure that Nil condition can be put at top without causing any problem it’s better not doing anything.
Thanks, this error raised by following translated code.
if ('A'..'Z') === ch
puts "ch is capital"
elsif Nil === ch
puts "ch is nil"
end
Maybe we should mention this in our syntax_and_semantics/case.html
, because this is still a surprise, This is also what the Ruby tries to avoid (matz’s principle of least surprise)
We should always check Nil out of case statement. e.g. like this:
ch : Char? = nil
if ch.nil?
puts "ch is nil"
else
case ch
when 'A'..'Z'
puts "ch is capital"
when others
# ...
end
end
This is bug. Could you report it please? Thank you!
To clarify, the code should compile just fine. ===
must return nil
if it can’t match the value, never give a compilation error.