pattern expression

패턴 표현식

나루 위키
둘러보기로 가기 검색하러 가기

패턴 표현식바인딩의 좌항이나 switch 표현식 안에 위치하는 표현식으로, 두 가지 역할을 가진다.

  1. 우항의 이 주어진 패턴에 "대응"하는지 확인하고, 그렇지 않으면 바인딩을 실패시킨다. (실패하지 않는 패턴을 완전하다고 한다.)
  2. 1이 성공했을 경우, 현재 영역에 0개 이상의 슬롯을 생성하고, 패턴에 대응하는 값으로 바인딩한다.

패턴 표현식은 파싱 과정에서는 동일한 문법을 가지며, 보통의 표현식과 마찬가지로 타입 추론의 대상이지만, 의미론은 다르다. 이를테면 이름은 항상 패턴으로, 그 이름을 가진 슬롯을 생성한다. (단, 정적 평가된 슬롯은 그렇지 않다. 후술.)

a := 42
word := "answer"

슬롯의 타입은 우항의 값으로부터 추론되나, 타입 힌트 표현식을 쓰면 강제할 수 있다. 이 경우 강제된 타입이 우항의 타입과 맞지 않으면 패턴은 타이핑 시점에 실패한다.

a: int := 42          -- `a := 42`와 같음
some_int: int := "42" -- 오류: `str`을 `int` 타입의 슬롯 `some_int`에 대입할 수 없음

좀 더 복잡한 패턴은 대부분 원 표현식의 의미를 역으로 뒤집은 것으로, 일반 표현식에서 어떤 값을 만드는 표현식은 패턴에서는 그 값의 부분에 재귀적으로 중첩된 패턴을 대응시킨다.

(a, b) := (42, 54)
(x: a, y: b) := (x: 42, y: 54) -- 위와 같음. [[라벨]]은 1:1 대응된다.

a@ := new 54
(a: int)@ := new 54 -- 위와 같음

이름 앞에 붙은 var은 슬롯이 변경 가능함을 가리킨다.

var a := 42
a = 54

(var a, b) := (42, 54)
a -= 1 -- OK
b += 1 -- 오류: `b`는 변경할 수 없음

완전

타이핑 과정을 거친 패턴 중 실패할 수 없는 것을 완전하다고 한다.

x := 54                 -- 우항에 아무 타입의 값이나 들어가도 됨
(a, b) := (42, "hello") -- 우항에 `(int, str)` 타입의 아무 값이나 들어가도 됨
x@ := new 54            -- 우항에 `int@` 타입의 아무 값이나 들어가도 됨

모든 리터럴 표현식은 패턴에 쓰일 때 완전하지 않다. 불완전한 패턴은 보통의 바인딩 문장에서는 사용할 수 없으며, if 표현식이나 switch 표현식 같이 불완전한 패턴을 허용하는 위치에서만 사용할 수 있다.

(x, 42) := ("foo", 0) -- 오류: `(str, int)` 타입의 패턴이 불완전함
if (x, 42) := ("foo", 0) {
    #"x = #x" println()
} else {
    "pattern mismatch" println() -- 이 문장만 실행된다.
}

리터럴 표현식을 포함하고 있더라도 해당 타입의 모든 값을 포함할 수 있다면 그 패턴은 완전하다. 범위 연산자를 사용했을 경우나 세미콜론으로 여러 패턴 중 하나에 대응될 경우가 여기에 해당한다.

(x, (true; false)) := (42, true) -- 허용

정적 평가

이름을 포함하지 않는 패턴 표현식은 정적 평가될 수 있다. 보통의 값 표현식에서 정적 평가 가능하지만 바깥의 이름을 포함하기 때문에 그러지 못하는 경우 static 표현식으로 묶을 수 있다.

if (static { "tr" ++ "ue" }) := "true" { true } else { false } --> true

정적 평가된 슬롯은 패턴에서 나타났을 때 슬롯을 새로 만들지 않고 그 슬롯의 값으로 간주된다.

static TRUE_STR := "true"
static FALSE_STR := "false"

if (TRUE_STR; FALSE_STR) := bool_str {
    bool_val := bool_str == TRUE_STR
} else {
    fail("invalid bool_str")
}

기본 문법

아래 포함되지 않은 표현식은 패턴 표현식으로 쓰일 수 없다.

표현식 패턴 위치에서의 의미
리터럴 해당 리터럴 값에 대응 (리터럴 접사를 허용함)
이름 표현식 이름 슬롯에 대응하거나, 정적 평가된 슬롯은 그 값에 대응
괄호 표현식 괄호 안의 패턴에 재귀적으로 대응
레코드 표현식 레코드 위치의 패턴에 재귀적으로 대응
컬렉션 표현식 컬렉션 위치의 패턴에 재귀적으로 대응
필드 표현식 필드 슬롯에 대응하거나, 정적 평가된 슬롯은 그 값에 대응
호출 표현식 호출되는 값 표현식에 따라 대응 방법이 달라짐
static 표현식 해당 값 표현식을 정적 평가한 값에 대응
범위 연산자 왼쪽·오른쪽 패턴이 리터럴이며, 해당 범위에 대응함을 가리킴
역참조 연산자 참조가 가리키는 패턴에 재귀적으로 대응
타입 힌트 연산자 왼쪽 패턴의 타입이 오른쪽 타입임을 가리킴
var 패턴이 슬롯을 가리키고 변경 가능함을 가리킴
세미콜론 패턴들이 정적 평가 가능하며, 각 패턴 중 아무 것에나 대응함을 가리킴