Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

패턴 #77

Open
simoniful opened this issue Dec 6, 2022 · 0 comments
Open

패턴 #77

simoniful opened this issue Dec 6, 2022 · 0 comments

Comments

@simoniful
Copy link
Owner

simoniful commented Dec 6, 2022

패턴(pattern)은 단일 값 또는 합성 값의 구조를 나타낸다
예를 들어, 튜플 (1, 2) 의 구조는 쉼표로 구분한 두 원소의 목록이 된다
패턴은 어떤 특별한 값 보단 값의 구조를 나타내기 때문에, 다양한 값과 맞춰볼 수 있다
구체적인 사례로, (x, y) 라는 패턴은 튜플 (1, 2) 및 어떤 다른 두 원소의 튜플과도 맞아떨어진다
패턴을 값과 맞춰보는 것에 더해, 합성 값의 일부 또는 전체를 뽑아내서 각 부분을 상수나 변수 이름에 연결할 수도 있다

스위프트에는, 두 종류의 기본 패턴이 있는데
어떤 종류의 값과 성공적으로 일치하는 패턴,
런타임에 지정된 값과 일치하지 않는 패턴이 있다

첫 번째 종류의 패턴은 단순 변수, 상수, 및 옵셔널 바인딩 안의 값을 해체하는(destructuring)데 사용한다
이는 와일드카드 패턴, 식별자 패턴 및 이를 포함하는 모든 값 바인딩 또는 튜플 패턴이 포함된다
이러한 패턴에 타입 명시 주석을 지정하면 특정 타입 값하고만 맞춰보도록 이들을 구속할 수 있다

두 번째 종류의 패턴은 전체 패턴 맞춤(full pattern matching)에 사용하는데,
여기선 맞춰보려는 값이 런타임 시기에 없을 수도 있다
여기에는 열거형 case 패턴, 옵셔널 패턴, 표현식 패턴, 및 타입-변환 패턴이 있다
이러한 패턴은 switch 문의 case 라벨, do 문의 catch 절, if, while, guard, for-in 문의 조건에 사용된다

캡쳐 2022-12-06 오후 2 59 20

와일드카드 패턴(Wildcard Pattern)

와일드카드 패턴(wildcard pattern)은 모든 값과 매칭한 다, 이를 무시하며 밑줄(_)로 구성된다
매칭되는 값에 상관없이 와일드카드 패턴을 사용한다
ex. 다음 코드는 닫힌 범위 1...3 을 반복하면서, 각 반복문 회차에서 범위의 현재 값은 무시된다

for _ in 1...3 {
    // Do something three times.
}

캡쳐 2022-12-06 오후 3 12 03

식별자 패턴

식별자 패턴은 임의의 값과 일치하며 일치된 값을 변수 또는 상수 이름에 바인딩한다
예를 들어, 다음 상수 선언에서 someValue는 Int 타입의 값 42와 일치하는 식별자 패턴이다

let someValue = 42

매칭이 성공하면 값 42가 상수 이름 someValue에 바인딩(할당)된다

변수 또는 상수 선언의 왼쪽에 있는 패턴이 식별자 패턴일 때,
식별자 패턴은 암시적으로 값 바인딩 패턴의 하위 패턴이 된다

캡쳐 2022-12-06 오후 3 14 27

값 바인딩 패턴

값 바인딩 패턴은 일치하는 값을 변수 또는 상수 이름으로 바인딩한다
일치하는 값을
상수 이름에 바인딩하는 값 바인딩 패턴은 let 키워드로 시작하고
변수 이름에 바인딩하는 패턴은 var 키워드로 시작한다

값 바인딩 패턴 내의 식별자 패턴은 새 명명된 변수 또는 상수를 일치하는 값에 바인딩한다
ex. 튜플의 요소를 분해하고 각 요소의 값을 해당 식별자 패턴에 바인딩할 수 있다

let point = (3, 2)
switch point {
    // Bind x and y to the elements of point.
case let (x, y):
    print("The point is at (\(x), \(y)).")
}
// Prints "The point is at (3, 2)."

위의 예제에서는 튜플 패턴(x, y)의 각 식별자 패턴이 분포하도록 한다
이런 동작 때문에, case let (x, y): 와 case (let x, let y): 라는 switch 문 case에 매칭하는 값은 똑같다

캡쳐 2022-12-06 오후 3 19 14

튜플 패턴

튜플 패턴(tuple pattern)은 쉼표로 구분한 0 개 이상의 패턴 목록을 괄호로 테두리 쳐 표현한다
튜플 패턴은 해당하는 튜플 타입의 값과 매칭한다

타입 명시 주석을 사용하여 특정 타입의 튜플 유형과 일치하도록 튜플 패턴을 제한할 수 있다
ex.상수 선언 let (x, y): (Int, Int) = (1, 2) 안의 (x, y): (Int, Int) 라는 튜플 패턴은 그 안의 원소가 둘 다 Int 일 때만 매칭된다

튜플 패턴을 for-in 문 안의 패턴이나 변수 또는 상수 선언 안의 패턴으로 사용하는 경우,
와일드카드 패턴, 식별자 패턴, 옵셔널 패턴, 이를 담은 다른 튜플 패턴만을 포함할 수 있다
예를 들어, 다음 코드는 유효하지 않은데 튜플 패턴 (x, 0) 안의 원소 0 이 표현식 패턴이기 때문이다

let points = [(0, 0), (1, 0), (1, 1), (2, 0), (2, 1)]
// This code isn't valid.
for (x, 0) in points {
    /* ... */
}

단일 요소를 포함하는 튜플 패턴 주위의 괄호는 아무런 영향을 미치지 않는다
패턴이 해당 단일 요소 유형의 값과 매칭된다
예를 들어, 다음은 모두 같다

let a = 2        // a: Int = 2
let (a) = 2      // a: Int = 2
let (a): Int = 2 // a: Int = 2

캡쳐 2022-12-06 오후 4 08 05

열거형 케이스 패턴

열거형 case 패턴(enumeration case pattern)은 기존 열거형 타입의 case 와 매칭한다
열거형 case 패턴은 switch 문의 case 라벨 안에서
그리고 if, while, guard, for-in 문의 조건 안에서 나타난다

맞춰보려는 열거형 case 값에 어떤 연관 값이 있으면,
해당하는 열거형 case 패턴에도 반드시 각각의 연관 값마다
한 원소씩 담은 튜플 패턴을 지정해야 한다

switch 문을 써서 연관 값을 담은 열거형 case 와 맞춰보는 예제는 Associated Values 페이지 부분을 보도록하자

열거형 case 패턴은 해당 case 를 옵셔널 안에 포장한 값과도 맞춰본다
이 단순해진 구문은 옵셔널 패턴을 생략하게 한다
Optional은 열거형으로 구현하기 때문에
똑같은 swift 구문 안에 .none 과 .some 이 열거형 타입의 case 로 나타날 수 있다는 걸 기억하도록 하자

enum SomeEnum { case left, right }
let x: SomeEnum? = .left
switch x {
case .left:
    print("Turn left")
case .right:
    print("Turn right")
case nil:
    print("Keep going straight")
}
// Prints "Turn left"

캡쳐 2022-12-06 오후 4 32 13

옵셔널 패턴

옵셔널 패턴(optional pattern)은 Optional 열거형의 some(Wrapped) case 안에 포장한 값과 매칭한다
옵셔널 패턴은 식별자 패턴과 그 바로 뒤의 물음표로 구성하며 열거형 case 패턴과 동일한 곳에 나타난다

옵셔널 패턴은 Optional 열거형 case 패턴의 수월한 구문이기 때문에 다음은 서로 같다

let someOptional: Int? = 42

// Match using an enumeration case pattern.
if case .some(let x) = someOptional {
    print(x)
}

// Match using an optional pattern.
if case let x? = someOptional {
    print(x)
}

옵셔널 패턴은 편리한 방법을 제공하여 for-in 문의 옵셔널 값 배열을 반복하는데, nil이 아닌 원소에만 반복문 본문을 실행한다

let arrayOfOptionalInts: [Int?] = [nil, 2, 3, nil, 5]

// Match only non-nil values.
for case let number? in arrayOfOptionalInts {
    print("Found a \(number)")
}
// Found a 2
// Found a 3
// Found a 5

캡쳐 2022-12-06 오후 4 35 36

타입 캐스팅 패턴

두 개의 타입 변환 패턴이 있는데
is 패턴과 as 패턴이 있다
is 패턴은 switch 문의 case 라벨에만 나타납니다
is 와 as 패턴의 형식은 다음과 같다

is type
pattern as type

is 패턴은 런타임에 해당 값의 타입이 is 패턴 오른쪽에 지정한 타입, 또는 해당 타입의 하위 클래스와 동일한지 매칭한다
is 패턴은 타입 변환을 한다는 점에선 is 연산자 같이 동작하지만 반환 타입을 버린다

as 패턴은 런타임에 하당 값의 타입이 as 패턴 오른쪽에 지정한 타입, 또는 해당 타입의 하위 클래스와 동일한지 매칭한다
매칭이 성공하면, 매칭한 값의 타입을 as 패턴 오른쪽에서 지정한 패턴(pattern)으로 캐스팅한다

switch 문을 써서 is 와 as 패턴으로 값을 맞추는 예제는, Type Casting for Any and AnyObject 페이지 부분을 보도록하자

캡쳐 2022-12-06 오후 4 41 31

표현식 패턴

표현식 패턴(expression pattern)은 표현식의 값을 나타낸다
표현식 패턴은 switch 문의 case 라벨 안에서만 나타난다

표현식 패턴이 나타내는 표현식과 입력 표현식 값의 비교는 스위프트 표준 라이브러리의 ~= 연산자로 수행한다
~= 연산자가 true 를 반환하면 매칭이 성공한 경우다
기본적으로 ~= 연산자는 == 연산자로 동일한 타입의 두 값을 비교한다
아래 예제에서 보는 것처럼, 범위 안에 값이 담겼는지를 검사하여 값을 값의 범위와도 매칭할 수 있다

let point = (1, 2)

switch point {
case (0, 0):
    print("(0, 0) is at the origin.")
case (-2...2, -2...2):
    print("(\(point.0), \(point.1)) is near the origin.")
default:
    print("The point is at (\(point.0), \(point.1)).")
}
// Prints "(1, 2) is near the origin."

~= 연산자를 중복 정의(overload)하여 자신만의 표현식 맞춤 동작을 제공할 수도 있다
예를 들어, 위의 예제를 재작성하여
기존의 point 표현식을 String으로 구성된 point의 표현식과 비교하게 구성할 수 있다

// Overload the ~= operator to match a string with an integer.
func ~= (pattern: String, value: Int) -> Bool {
    return pattern == "\(value)"
}

switch point {
case ("0", "0"):
    print("(0, 0) is at the origin.")
default:
    print("The point is at (\(point.0), \(point.1)).")
}
// Prints "The point is at (1, 2)."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant