case

case

A case is a control expression which functions a bit like pattern matching. It allows writing a chain of if-else-if with a small change in semantic and some more powerful constructs.

In its basic form, it allows matching a value against other values:

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

Note that === is used for comparing an expression against a case's value.

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?
  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

Finally, you can omit the case's value:

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

This sometimes leads to code that is more natural to read.

Tuple literal

When a case expression is a tuple literal there are a few semantic differences if a when condition is also a tuple literal.

Tuple size must match

case {value1, value2}
when {0, 0} # OK, 2 elements
  # ...
when {1, 2, 3} # Compiler error, because it will never match
  # ...
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

Implicit-object allowed

case {value1, value2}
when {.even?, .odd?}
  # Matches if value1.even? && value2.odd?
end

Comparing against a type will perform an is_a? check

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

To the extent possible under law, the persons who contributed to this workhave waived
all copyright and related or neighboring rights to this workby associating CC0 with it.
https://crystal-lang.org/docs/syntax_and_semantics/case.html

在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号

意见反馈
返回顶部