하위 case를 쓰는 매치 표현식
하위 case를 쓰는 매치 표현식 (Match Expressions with Sub Cases)
매치 표현식의 case 뒤에 if 키워드로 도입되는 또 다른 하위 매치(sub-match) 표현식을 붙일 수 있게 해주는 실험적 기능이에요. 중첩 패턴 검사를 더 읽기 좋게 만들어 줍니다.
본문
매치 표현식의 case는 if 키워드로 도입되는 또 다른 하위 매치 표현식으로 이어질 수 있어요. 예를 들어:
enum Version:
case Legacy
case Stable(major: Int, minor: Int)
case class Document(title: String, version: Version)
def version(d: Option[Document]) = d match
case Some(x) if x.version match
case Version.Stable(m, n) if m > 2 => s"$m.$n"
case Version.Legacy => "legacy"
case _ => "unsupported"
assert(version(Some(Document("...", Version.Stable(3, 1)))) = "3.1")
assert(version(Some(Document("...", Version.Stable(2, 1)))) = "unsupported")
assert(version(Some(Document("...", Version.Legacy))) = "legacy")
assert(version(Some(Document("...", None))) = "unsupported")
하위 매치 표현식의 case들은 바깥 case가 일치할 때에만 검사됩니다. 하위 매치의 검사 대상(scrutinee)은 바깥 패턴에서 묶인 변수를 참조할 수 있어요. 그러면 하위 매치의 평가는 평소대로 진행됩니다. 예를 들어 version이 Some(Document("...", Version.Stable(3, 1)))에 적용되면, 첫 번째 바깥 패턴(즉 Some(x))이 일치해서, 검사 대상 Version.Stable(3, 1)로 하위 매치 표현식이 평가되고 "3.1"이 나와요.
하위 매치 표현식의 case들은 완전(exhaustive)할 필요가 없어요. 만약 완전했다면 하위 매치가 아예 필요 없을 거예요. 첫 번째 case의 본문에서 평범한 매치(case Some(x) => x.version match ...)로 충분하니까요. 하위 case 중 어느 것도 성공하지 못하면, 제어 흐름은 바깥 매치 표현식으로 돌아가서 마치 현재 case가 일치하지 않았던 것처럼 진행돼요. 예를 들어 Some(Document("...", Version.Stable(2, 1)))은 첫 번째 패턴에는 일치하지만 그 하위 case 중 어느 것에도 일치하지 않아서, 결과로 "unsupported"를 얻습니다.
동기 (Motivation)
하위 매치가 없으면 보통 기본 case(default case)나 바깥 패턴 중 하나를 중복해서 쓰게 돼요. 즉 이렇게 쓰거나
def version(d: Option[Document]) = d match
case Some(x) => x.version match
case Version.Stable(m, n) if m > 2 => s"$m.$n"
case Version.Legacy => "legacy"
case _ => "unsupported"
case _ => "unsupported"
이렇게 씁니다:
def version(d: Option[Document]) = d match
case Some(Document(_, Version.Stable(m, n))) if m > 2 => s"$m.$n"
case Some(Document(_, Version.Legacy)) => "legacy"
case _ => "unsupported"
세부 사항 (Details)
하위 case는 다음을 허용해요:
- 임의의 중첩. 예를 들어 하위-하위 매치가 지원돼요.
- 불리언 가드의 교차. 예를 들어
case Some(x: Int) if x != 0 if x match .... - 하위 매치 검사 대상에 대한 패턴 추출기와 계산의 교차.
하위 case는 다음에 대해 지원돼요:
- 매치 절 (match clauses)
- catch 절
- 부분 함수 (partial functions)
catch 절과 비슷하게, 단일 case를 가진 매치 표현식은 이제 한 줄에(괄호 없이) 쓸 수 있어요. 예를 들어 Some(1) match case Some(x) => x처럼요.
완전성(exhaustivity)과 도달성(reachability) 검사는 불리언 가드와 비슷하게, 하위 case가 부분적(partial)이라고 보수적으로 가정해요.
하위 매치는 바깥 매치가 인라인될 때 인라인되며, 평범한 매치 표현식과 같은 의미론을 가져요.