목차
📁 match-with expression
값의 형태에 따라 다른 행동을 수행하도록 하는 expression이다.
해당 표현은 expression이므로 값으로 도출된다.
기본형은 다음과 같다.
match [expression] with
| [pattern1] -> [expression1]
| [pattern2] -> [expression2]
...
| [patternN] -> [expressionN]
위의 pattern들은 상수(constant) 혹은 변수(variable)로 구성되어 있다.
만약 [pattern1]부터 Wildcard라면, 그 밑으로는 무시된다.
위 expression1, ... N 들의 타입이 같아야한다.
match with 구문을 실행하는 과정은 다음과 같다.
- expression을 계산한다.
- 위의 계산 결과를 pattern1과 매칭한다.
- 매칭되는 경우 expression1을 계산하고, 그 결과가 전체 match-with expression의 결과가 된다.
- 매칭을 실패하는 경우 pattern2와 매칭한다.
- ...
처리하지 않은 형태가 있을 경우 warning이 발생한다. 예를 들면 다음과 같은 경우가 있다.
[1; 2; 3]
| [] -> ~~
| [h] -> ~~
| [h1; h2] -> ~~
위 코드에서 원소 3개짜리를 처리하지 않았기 때문에 warning이 발생한다.
📝 Example1
📌 패턴은 상수인지 변수인지에 따라 다르게 동작한다.
패턴이 상수인 경우, [expression] 값이 패턴과 일치하는지를 매칭한다.
일치할 경우 매칭에 성공하고, 불일치할 경우 매칭에 실패한다.
패턴이 변수인 경우, [expression] 값을 변수에 바인딩한다.
이 경우에는 항상 매칭에 성공한다.
예시는 다음과 같다.
module F = Format
module Fib = struct
let rec fib i =
match i with
| 0 -> 0 (* when i is 0 *)
| 1 -> 1 (* when i is 1 *)
| n -> fib (n-2) + fib (n-1) (* otherwise *)
end
let _ =
let _ = F.printf "Res: %d\n" (Fib.fib 0) in
let _ = F.printf "Res: %d\n" (Fib.fib 1) in
let _ = F.printf "Res: %d\n" (Fib.fib 2) in
F.printf "Res: %d\n" (Fib.fib 3)
위 fib 재귀함수는 음수가 오면 무한반복한다. 이를 커버하기 위해 아래와 같은 방법을 이용한다.
match i with
| 0 -> 0
| n when n > 0 -> ~~
| n -> ~~
이때 음수를 커버하겠다는 목적으로 when n < 0 구문을 마지막 패턴의 n 뒤에 쓰게 되면 오류가 발생한다.
pattern에 when 구문이 존재하면 컴파일러는 무조건 '부분적 커버'라고 생각하기 때문에, 마지막 변수에는 when절이 존재하면 안된다.
📌 [patternN]에 있는 변수는 무조건 [expressionN]에서 사용되어야 한다.
쓰지 않으면 오류가 난다. 왱?
🔎 Caution1 : variables in patterns
패턴내의 변수는 값과 바인딩되므로 항상 매칭에 성공한다.때문에 변수가 앞 패턴에 등장하는 경우, 이후의 패턴은 매칭될 기회를 잃는다.

위 예시에서 pattern의 변수 x, y는 binding occurrence이며, 이는 바인딩 발생이라는 뜻이다.
위에서 x = 0, y = 1이라과 정의하였어도 패턴 내에 들어오면 x, y를 0과 1로 치환하여 생각하는게 아니라, 무조건 i를 x, y에 바인딩한다는 뜻이다.
이때 패턴 내의 x, y 변수는 바깥의 x, y를 shadowing하며, 이름만 같을 뿐 서로 다른 변수이다.
📝 Example 2
📌 [expression]에 임의의 expression을 사용할 수 있다.
📌 [patternN]에 Wildcard를 사용할 수 있다.
[patternN]에 Wildcard를 사용하게 되면 변수와 같이 항상 매칭에 성공하지만, 매칭된 [expression] 결과값을 [expressionN]에서 사용하지 않겠다는 의미이다.
예시는 다음과 같다.
let _ =
let even_or_odd i =
match i mod 2 with
| 0 -> F.printf "Even\n"
| 1 -> F.printf "Odd\n"
| _ -> (* Is this pattern required? *) F.printf "Unknwon\n"
in
let _ = even_or_odd 0 in (* Even *)
let _ = even_or_odd 1 in (* Odd *)
let _ = even_or_odd 2 in (* Even *)
even_or_odd 3 (* Odd *)
위 예시에서 [expression]에 i mod 2라는 임의의 expression을 사용하였다.
🔎 Caution2 : exhaustive matching
위 예시에서 Wildcard 패턴을 제외하면 컴파일 warning이 발생한다.i mod 2 결과는 무조건 0 혹은 1이라고 생각해서 wildcard를 제거하면 안된다.
컴파일러는 expression의 결과값이 아니라 타입을 기반으로 패턴매칭을 검사하기 때문에,위와 같이 결과값이 int인 경우 모든 int에 대해 커버해야한다.
📝 Example3
📁 패턴 매칭 사용 시 주의사항
Caution1 : variables in patterns
Caution2 : exhaustive matching
Caution3 : type of pattern matching expression