case¶
case
是一种控制表达式,其功能有点像模式匹配。它允许编写一系列 if-else-if,但语义略有变化,并提供一些更强大的构造。
在基本形式中,它允许将一个值与其他值匹配。
case exp
when value1, value2
do_something
when value3
do_something_else
else
do_another_thing
end
# The above is the same as:
tmp = exp
if value1 === tmp || value2 === tmp
do_something
elsif value3 === tmp
do_something_else
else
do_another_thing
end
为了将表达式与 case
的主题进行比较,编译器使用 case 子集运算符 ===
。它在 Object
上定义为一个方法,可以被子类覆盖以在 case 语句中提供有意义的语义。例如,Class
将 case 子集定义为当对象是该类的实例时,Regex
定义为当值匹配正则表达式时,以及 Range
定义为当值包含在该范围内时。
如果 when
的表达式是一个类型,则使用 is_a?
。此外,如果 case 表达式是一个变量或一个变量赋值,则变量的类型会被限制。
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
您可以在 when
中使用隐式对象语法在 case
的表达式上调用方法。
case num
when .even?
do_something
when .odd?
do_something_else
end
# The above is the same as:
tmp = num
if tmp.even?
do_something
elsif tmp.odd?
do_something_else
end
您可以在 when
条件后使用 then
将主体放置在一行上。
case exp
when value1, value2 then do_something
when value3 then do_something_else
else do_another_thing
end
最后,您可以省略 case
的值。
case
when cond1, cond2
do_something
when cond3
do_something_else
end
# The above is the same as:
if cond1 || cond2
do_something
elsif cond3
do_something_else
end
这有时会导致代码更容易阅读。
元组字面量¶
当 case 表达式是一个元组字面量时,如果 when
条件也是一个元组字面量,则存在一些语义差异。
元组大小必须匹配¶
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
允许使用下划线¶
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
与类型比较将执行 is_a? 检查¶
case {value1, value2}
when {String, Int32}
# Matches if value1.is_a?(String) && value2.is_a?(Int32)
# The type of value1 is known to be a String by the compiler,
# and the type of value2 is known to be an Int32
end
穷举 case¶
使用 in
而不是 when
会生成一个穷举 case 表达式;在穷举 case 中,省略任何必需的 in
条件将是一个编译时错误。穷举 case
不能包含任何 when
或 else
子句。
编译器支持以下 in
条件
联合类型检查¶
如果 case
的表达式是一个联合值,则每个联合类型都可以用作条件。
# var : (Bool | Char | String)?
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
布尔值¶
如果 case
的表达式是一个 Bool
值,则 true
和 false
字面量可以用作条件。
# var : Bool
case var
in true
do_something
in false
do_something_else
end
枚举值¶
如果 case
的表达式是一个非标志枚举值,则它的成员可以用作条件,既可以是常量,也可以是谓词方法。
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
end
元组字面量¶
这些条件必须穷举 case
表达式元素的所有可能组合。
# value1, value2 : Bool
case {value1, value2}
in {true, _}
# value1 is true, value2 can be true or false
do_something
in {_, false}
# here value1 is false, and value2 is also false
do_something_else
end
# Error: case is not exhaustive.
#
# Missing cases:
# - {false, true}