study record

[Swift] 패턴 본문

Swift/스위프트 프로그래밍

[Swift] 패턴

asong 2022. 1. 20. 10:28

* 이 글은 책 "스위프트 프로그래밍"을 읽고 작성한 글입니다.

 

스위프트에는 문법에 응용할 수 있는 다양한 종류의 패턴이 있다. 여러 패턴을 잘 숙지하면 스위프트 코드의 양을 줄이는 효과는 물론, 스위프트 문법을 좀 더 잘 활용할 수 있다.

 

패턴은 ‘단독 또는 복합 값의 구조를 나타내는 것’이고 패턴 매칭은 ‘코드에서 어떤 패턴의 형태를 찾아내는 행위’라고 할 수 있다. 쉽게 말해 이러이러한 것을 표현하고 싶다면 이러이러한 패턴을 통해 표현하면 된다고 이해하면 된다. 대부분의 패턴은 switch, if, guard, for 등의 키워드와 아주 친하며 두 개 이상의 키워드가 합을 이뤄 동작한다. 대부분의 패턴은 switch에서 강력하게 작용한다.

 

스위프트의 패턴은 크게 두 종류로 나뉜다.

  • 값을 해체(추출)하거나 무시하는 패턴
    • 와일드카드 패턴, 식별자 패턴, 값 바인딩 패턴, 튜플 패턴
  • 패턴 매칭을 위한 패턴
    • 열거형 케이스 패턴, 옵셔널 패턴, 표현 패턴, 타입캐스팅 패턴

 

와일드카드 패턴

와일드카드 패턴(Wildcard Pattern)은 와일드카드 식별자()를 사용한다. 와일드카드 식별자(_)를 사용한다는 것은 ‘이 자리에 올 것이 무엇이든간에 상관하지 마라’는 뜻이다. switch 구문이나 for-in 구문에서 사용할 수 있다.

// 와일드카드 패턴의 사용
let string: String = "ABC"

switch string {
	case _: print(string)  //어떤 값이 와도 상관 없으므로 실행된다.
}

let yagom = ("yagom", 99, "Male")
switch yagom {
	case ("yagom", _, _): print("hello yagom") //첫번째 요소가 "yagom"일 때만 실행된다.
	case (_, _, _): print("who cares") // 그 외 언제든지 실행된다.
}

for _ in 0..<2 {
	print("hello")
}

 

식별자 패턴

식별자 패턴은 변수 또는 상수의 이름에 알맞는 값을 하면 어떤 값과 매치시키는 패턴을 말한다.

let someValue: Int = 42

someValue 상수를 선언하는 동시에 값을 할당하려고 한다. someValue의 타입인 Int와 할당하려는 42의 타입이 매치된다면 someValue는 42라는 값의 식별자가 되므로 식별자 패턴이 성립된다.

 

 

값 바인딩 패턴

값 바인딩 패턴은 변수 또는 상수의 이름에 매치된 값을 바인딩하는 것이다. 값 바인딩 패턴의 일종인 식별자 패턴은 매칭되는 값을 새로운 이름의 변수 또는 상수에 바인딩한다. 예를 들어 튜플의 요소를 해체하여 그에 대응하는 식별자 패턴에 각각의 요소 값을 바인딩하는 것이다.

let yagom = ("yagom", 99, "Male")

// name, age, gender를 yagom의 각각의 요소와 바인딩한다.
switch yagom {
case let (name, age, gender) : print("name: \(name), age: \(age), gender: \(gender)")
}

switch yagom {
case let (name, _, gender) : print("name: \(name), gender: \(gender)")
}
// 값 바인딩 패턴은 와일드카드 패턴과 결합하여 유용하게 사용될 수 있다.

 

튜플 패턴

튜플 패턴은 소괄호(())내에 쉼표로 분리하는 리스트이다. 튜플 패턴은 그에 상응하는 튜플 타입과 값을 매치한다. 예를 들어 let (x, y): (Int, Int) = (1,2) 와 같이 상수를 선언한다면 (x, y): (Int, Int) 라고 사용된 튜플 패턴은 요소가 모두 Int 타입인 튜플하고만 매치된다는 뜻이다.

튜플 패턴을 for-in 구문 또는 변수나 상수 선언에서 사용한다면 와일드카드 패턴, 식별자 패턴, 옵셔널 패턴 등과 함께 사용할 수 있다.

switch (name, age, gender) {
case ("Jung", _, _): print("hello Jung")
default: print()
}

 

열거형 케이스 패턴

열거형 케이스 패턴은 값을 열거형 타입의 case와 매치시킨다. 열거형 케이스 패턴은 switch 구문의 case 레이블과 if, while, guard, for-in 구문의 case 조건에서 볼 수 있다. 만약 연관 값이 있는 열거형 케이스와 매치하려고 한다면 열거형 케이스 패턴에는 반드시 튜플 패턴이 함께 해야 한다.

let someValue: Int = 30

if case 0...100 = someValue {
	print("0 <= \(someValue) <= 100")
}

enum MainDish {
	case passta(taste: String)
	case pizza(dough: Strinng, topping: String)
	case chhicken(wiwthSauce: Bool)
	case rice
}

var dishes: [MainDish] = []

var dinneer: MainDish = .pasta(taste: "크림")
dishes.append(dinner)

if case .pasta(let taste) = dinner {
	print("\(taste) 파스타")
}

 

옵셔널 패턴

옵셔널 패턴은 옵셔널 또는 암시적 추출 옵셔널 열거형에 감싸져 있는 값을 매치시킬 때 사용한다. 옵셔널 패턴은 식별자 패턴 뒤에 물음표를 넣어 표기하며 열거형 케이스 패턴과 동일한 위치에 자리한다. 또 옵셔널 패턴은 옵셔널 값을 저장하는 배열의 for-in 구문을 통한 순환에서 nil이 아닌 값을 찾는 데도 유용하게 사용한다.

var optionalValue: Int? = 100

if case .some(let value) = optionalValue{
	print(value)
}

 

타입캐스팅 패턴

타입캐스팅 패턴에는 is 패턴과 as 패턴이 있다. is 패턴은 switch의 case 레이블에서만 사용할 수 있다. is 패턴은 is (TYPE_NAME)과 같이 쓸 수 있고 as 패턴은 SomePattern as (TYPE_NAME)과 같이 쓸 수 있다.

타입캐스팅 패턴은 타입캐스팅을 하거나 타입을 매치시킨다. is 패턴은 값의 타입이 is 우측에 쓰여진 타입 또는 그 타입의 자식클래스 타입이면 값과 매치시킨다. is 패턴은 as 연산자와 비슷한 역할을 하지만 반환된 결괏값은 신경쓰지 않는다는 차이가 있다.

as 패턴은 as 우측에 쓰여진 타입 또는 그 타입의 자식클래스 타입이면 값과 매치시킨다. 매치된다면 as 패턴이 원하는 타입으로 캐스팅된다.

let someValue: Any = 100

switch someValue {
// 타입이 Int 인지 확인하지만 캐스팅된 값을 사용할 수는 없다.
case is String: print("It's String")

// 타입 확인과 동시에 캐스팅까지 완료되어 value에 저장된다.
case let value as Int: print(value+1)
default: print("")
}

 

표현 패턴

표현 패턴은 표현식의 값을 평가한 결과를 이용한다. 표현 패턴은 switch 구문의 case 레이블에서만 사용할 수 있다. 표현 패턴은 스위프트 표준 라이브러리의 패턴 연산자인 ~= 연산자의 연산결과가 true를 반환하면 매치시킨다. ~= 연산자는 같은 타입의 두 값을 비교할 때 == 연산자를 사용한다. 표현 패턴은 정숫값과 정수의 범위를 나타내는 Range 객체와 매치시킬 수 있다.

표현 패턴은 매우 유용한 패턴 중 하나로 패턴 중 최고봉이다. 그 이유는 ~= 연산자를 중복 정의하거나 새로 정의하거나 구현해준다면 자신이 원하는대로 패턴을 완성시킬 수 있기 때문이다. 거기다 제네릭까지 추가하면 활용도가 더욱 높아진다.

'Swift > 스위프트 프로그래밍' 카테고리의 다른 글

[swift] ARC  (0) 2022.02.04
[Swift] where절  (0) 2022.01.24
[Swift] 타입 중첩  (0) 2022.01.19
[Swift] 프로토콜 지향 프로그래밍  (0) 2022.01.18
[Swift] 제네릭  (0) 2022.01.14