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}