[SWIFT] where 절

2021. 1. 19. 03:19SWIFT

반응형

저번 포스팅까지는 SWIFT의 패턴과 패턴 매칭에 대해 알아봤어요.

 

이번 포스팅에서는 조금 더 고급 문법인 where 절에 대해 알아보려고 합니다 :D

 

where 절은... 음 Database의 Query문을 짤 때 사용했던 기억이 있는데, 그 때도 조건을 추가할 때 사용했었던 것 같아요..🤞

SWIFT에서도 역시 where 절은 조건들을 추가할 때 사용할 수 있는 문법이랍니다.

 

where 절은 크게 두 가지의 용도로 사용된다고 해요..!!

 

첫번째로는 SWIFT의 패턴들과 결합하여 조건을 추가해줄 수 있어요.

두번째로는 타입에 대한 제약을 추가할 수 있대요. - 이 경우는 특정 프로토콜을 준수하게 하거나 하는 등의 역할을 하는 것 같아요.

 

그렇다면 오늘 포스팅은 이 where 절의 사용에 초점을 맞추어서 포스팅을 해볼게요 :)

 

 

값 바인딩(Value-Binding)과 where 절 사용 

우선 값 바인딩(Value-Binding) 패턴과 같이 활용하는 where 절의 사용 먼저 알아보도록 할게요.

 

역시 예시로 같이 알아볼게요~

let tuples: [(Int, Int)] = [(1, 2), (1, -1), (1, 0), (0, 2)]

for tuple in tuples {
    switch tuple {
    case let (x, y) where x == y: print("x == y")
    case let (x, y) where x == -y: print("x == -y")
    case let (x, y) where x > y: print("x > y")
    case (1, _): print("x == 1")
    case (_, 2): print("y == 2")
    default: print("Something else")
    }
}

/*
x == 1
x == -y
x > y
y == 2
*/

위의 구문을 실행시켜보면 예시와 같은 결과를 확인할 수 있을거에요.

 

여기서 where 절이 어떻게 사용되는지 느낌이 오시나요?

 

우선 값 바인딩 패턴으로 (x, y) 튜플에 각각의 값을 할당한 것은 알 수 있는데, 왜 전부 다른 문장이 실행이 될까요..?

바로 where 절을 이용해서 각 구문의 제약을 걸고 있기 때문이에요.

where 절 이후에 들어가는 구문들이 Bool 타입을 반환하는 문장임을 알 수 있죠?

 

간단하게 (1, 2)로만 한 번 볼게요.

x == y라는 식이 성립하지 않죠? (넘어가)

x == -y라는 식도 성립하지 않죠? (넘어가)

x > y라는 식도 성립하지 않죠? (넘어가)

(1, _)는 와일드 카드 패턴으로 성립하죠? ("x == 1" 출력)

 

어렵지 않죠?

 

그렇다면 where 절에 Bool 타입이 들어가면 되기 때문에, &&, || 논리 연산자도 활용할 수 있겠죠?

같이 예시로 볼게요.

let tuples: [(Int, Int)] = [(1, 2), (1, -1), (1, 0), (0, 2)]

var count: Int = 0

for tuple in tuples {
    switch tuple {
    case let (x, y) where x == y && count > 2: print("x == y")
    case let (x, y) where count < 2: print("\(x), \(y)")
    default: print("Nothing")
    }
    
    count += 1
}

/*
(1, 2)
(1, -1)
Nothing
Nothing
*/

이렇게 논리 연산자를 이용해서 여러 제약 조건도 넣을 수 있겠죠?

 

지금까지의 방법들을 활용해서 값 바인딩(Value-Binding) 패턴과 같이 사용할 수 있어요.

 

 

옵셔널(Optional)과 where 절 사용 

이번에는 옵셔널 패턴을 활용한 where 절의 사용이 어떻게 이루어지는지 알아볼게요.

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

for case let number? in arrayOfOptionalInts where number > 2 {
    print(number)
}

/*
3
5
*/

이번 패턴도 크게 어렵지 않죠.

 

이전 포스팅에서 했던 패턴에 대해 이해를 했다면 where 절의 사용이 크게 어렵지 않을 것 같아요.

 

 

표현 패턴(Expression Pattern)과 where 절 사용 

이번에는 표현 패턴을 활용해서 where 절과 함께 사용하는 예시를 통해 알아볼게요.

var point: (Int, Int) = (1, 2)

switch point {
    case (-2...2, -2...2) where point.0 != 0 && point.1 != 0: print("\(x), \(y)는 원점이 아닙니다")
    default: print("\(point.0), \(point.1)")
}

// (1, 2)는 원점이 아닙니다

이렇듯 표현 패턴과 매칭해서 같이 사용하면 코드의 줄을 조금 더 줄여서 사용할 수 있겠죠?

 

지금까지는 패턴과 조합하여 조건을 추가하는 방법의 where 절 사용에 대해 알아봤어요.

이제는 타입에 대한 제약을 추가하는 where 절 사용에 대해 알아볼게요.

 

 

Generic의 타입 제약 where 절 사용

제네릭(Generic)을 사용하면 여러 타입이 일반적으로 함수나 구조체 클래스에 들어올 수 있고 통용적(?)으로 사용할 수 있었죠.

그리고 제네릭(Generic)에 플레이스 홀더라는 것 기억나시나요? 

 

바로 이 플레이스 홀더도 타입 제약을 위해 사용을 했었는데, 역시 where 절을 사용해서도 제네릭(Generic) 타입에 타입을 제약해줄 수 있습니다.

 

예시로 볼게요!

// where 절을 활용한 타입 제약
func doubled<T>(integerValue: T) -> T where T: BinaryInteger {
    return integerValue * 2
}

// Generic의 플레이스 홀더를 사용한 타입 제약
func doubled<T: BinaryInteger>(integerValue: T) -> T {
    return integerValue * 2
}

이렇게 두 메소드를 보면 어떤 느낌이 드시나요?

 

둘다 T라는 타입이 BinaryInteger라는 프로토콜을 채택한 타입만 들어올 수 있다고 표현하고 있는게 눈에 들어오시나요?

 

결론적으로 두 메소드 동일한 표현입니다. 

즉, 동일하게 작동합니다.

 

다음 예시도 한 번 볼게요.

// where 절을 활용한 두 가지 타입 제약
func prints<T, U>(first: T, second: U) where T: CustomStringConvertible, U: CustomStringConvertible {
    print(first)
    print(second)
}

// Generic을 활용한 두 가지 타입 제약
func print<T: CustomStringConvertible, U: CustomStringConvertible>(first: T, second U) {
    print(first)
    print(second)
}

이 경우에도 위와 다른 점은 타입 제약을 두 가지 사용했다는 점입니다.

즉, where 절은 타입을 제약할 때 Generic의 사용과 같이 할 수 있다는 것입니다.

 

이러한 where 절을 사용하면 조금 더 고급지게 SWIFT의 문법을 사용해서 코딩할 수 있을 것 같네요..‼️

 

 

오늘은 where 절에 대해 포스팅을 해보았습니다 :D

혹시 포스팅 내용에 틀린 점이나 궁금한 점이 있으면 말씀해주세요~ 

 


참고 레퍼런스

  • SWIFT 스위프트 프로그래밍 3판 - 야곰
반응형