case
In its basic form, it allows matching a value against other values:
For comparing an expression against a case
‘s value the case equality operator ===
is used. It is defined as a method on Object and can be overridden by subclasses to provide meaningful semantics in case statements. For example, defines case equality as when an object is an instance of that class, Regex as when the value matches the regular expression and as when the value is included in that range.
If a when
‘s expression is a type, is_a?
is used. Additionally, if the case expression is a variable or a variable assignment the type of the variable is restricted:
case var
when String
# var : String
do_something
when Int32
# var : Int32
do_something_else
else
# here var is neither a String nor an Int32
do_another_thing
end
# The above is the same as:
if var.is_a?(String)
do_something
elsif var.is_a?(Int32)
do_something_else
else
do_another_thing
end
You can invoke a method on the case
‘s expression in a when
by using the implicit-object syntax:
case num
when .even?
when .odd?
do_something_else
end
# The above is the same as:
tmp = num
if tmp.even?
elsif tmp.odd?
do_something_else
end
case exp
when value1, value2 then do_something
when value3 then do_something_else
else do_another_thing
end
Finally, you can omit the case
‘s value:
This sometimes leads to code that is more natural to read.
When a case expression is a tuple literal there are a few semantic differences if a when
condition is also a tuple literal.
case {value1, value2}
when {0, 0} # OK, 2 elements
# ...
when {1, 2, 3} # Syntax error: wrong number of tuple elements (given 3, expected 2)
# ...
end
Underscore allowed
case {value1, value2}
when {0, _}
# Matches if 0 === value1, no test done against value2
when {_, 0}
# Matches if 0 === value2, no test done against value1
end
case {value1, value2}
when {.even?, .odd?}
# Matches if value1.even? && value2.odd?
end
Comparing against a type will perform an is_a? check
Exhaustive case
Using in
instead of when
produces an exhaustive case expression; in an exhaustive case, it is a compile-time error to omit any of the required in
conditions. An exhaustive case
cannot contain any when
or else
clauses.
If case
‘s expression is a union value, each of the union types may be used as a condition:
case var
in String
# var : String
in Char
# var : Char
in Bool
# var : Bool
in nil # or Nil, but .nil? is not allowed
# var : Nil
end
Bool values
If case
‘s expression is a Bool
value, the true
and false
literals may be used as conditions:
# var : Bool
case var
in true
do_something
in false
do_something_else
end
If case
‘s expression is a non-flags enum value, its members may be used as conditions, either as constant or predicate method.
enum Foo
X
Y
Z
end
# var : Foo
case var
in Foo::X
# var == Foo::X
in .y?
# var == Foo::Y
in .z? # :z is not allowed
# var == Foo::Z
Tuple literals
The conditions must exhaust all possible combinations of the case
expression’s elements: