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:

    1. case var
    2. when String
    3. # var : String
    4. do_something
    5. when Int32
    6. # var : Int32
    7. do_something_else
    8. else
    9. # here var is neither a String nor an Int32
    10. do_another_thing
    11. end
    12. # The above is the same as:
    13. if var.is_a?(String)
    14. do_something
    15. elsif var.is_a?(Int32)
    16. do_something_else
    17. else
    18. do_another_thing
    19. end

    You can invoke a method on the case‘s expression in a when by using the implicit-object syntax:

    1. case num
    2. when .even?
    3. when .odd?
    4. do_something_else
    5. end
    6. # The above is the same as:
    7. tmp = num
    8. if tmp.even?
    9. elsif tmp.odd?
    10. do_something_else
    11. end
    1. case exp
    2. when value1, value2 then do_something
    3. when value3 then do_something_else
    4. else do_another_thing
    5. 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.

    1. case {value1, value2}
    2. when {0, 0} # OK, 2 elements
    3. # ...
    4. when {1, 2, 3} # Syntax error: wrong number of tuple elements (given 3, expected 2)
    5. # ...
    6. end

    Underscore allowed

    1. case {value1, value2}
    2. when {0, _}
    3. # Matches if 0 === value1, no test done against value2
    4. when {_, 0}
    5. # Matches if 0 === value2, no test done against value1
    6. end
    1. case {value1, value2}
    2. when {.even?, .odd?}
    3. # Matches if value1.even? && value2.odd?
    4. 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:

    1. case var
    2. in String
    3. # var : String
    4. in Char
    5. # var : Char
    6. in Bool
    7. # var : Bool
    8. in nil # or Nil, but .nil? is not allowed
    9. # var : Nil
    10. end

    Bool values

    If case‘s expression is a Bool value, the true and false literals may be used as conditions:

    1. # var : Bool
    2. case var
    3. in true
    4. do_something
    5. in false
    6. do_something_else
    7. end

    If case‘s expression is a non-flags enum value, its members may be used as conditions, either as constant or predicate method.

    1. enum Foo
    2. X
    3. Y
    4. Z
    5. end
    6. # var : Foo
    7. case var
    8. in Foo::X
    9. # var == Foo::X
    10. in .y?
    11. # var == Foo::Y
    12. in .z? # :z is not allowed
    13. # var == Foo::Z

    Tuple literals

    The conditions must exhaust all possible combinations of the case expression’s elements: