Optional
은 swift에만 있는 기능 중 하나입니다.
그래서 저는 처음에 swift 문법을 공부하면서 제일 어려웠던 부분이었습니다.
그러면 Optional
이 어떻게 구현되어 있는지 한 번 살펴볼까요?
자세한 내용은 Apple > swift > public > ... > Optional.swift에서 확인할 수 있습니다.
map
과 flatMap
이 Optional
과 같은 파일에 있어서 의외였는데요😳
Optional.map
@inlinable
public func map<U>(
_ transform: (Wrapped) throws -> U
) rethrows -> U? {
switch self {
case .some(let y):
return .some(try transform(y))
case .none:
return .none
}
}
let possibleNumber: Int? = Int("42")
let possibleSquare = possibleNumber.map { $0 * $0 }
print(possibleSquare)
// Prints "Optional(1764)"
let noNumber: Int? = nil
let noSquare = noNumber.map { $0 * $0 }
print(noSquare)
// Prints "nil"
이
Optional
인스턴스가nil
이 아닐 때 주어진 클로저를 평가하여 래핑되지 않은 값을 매개변수로 전달합니다. 선택 사항이 아닌 값을 반환하는 클로저와 함께map
메서드를 사용하세요. 이 예에서는 선택적 정수에 대해 산술 연산을 수행합니다.
배열 요소를 연산하는 map
하고는 조금 느낌이 다르더라고요!
Optional
타입 연산을 위한 map
처럼 보입니다.
그러면 다시 돌아가서 Optional를 살펴봅시다!
Optional
@frozen
public enum Optional<Wrapped>: ExpressibleByNilLiteral {
case none
case some(Wrapped)
@_transparent
public init(_ some: Wrapped) { self = .some(some) }
...
}
@frozen
해당 어트리뷰트는 Swift Documentation - Attributes에서 자세히 볼 수 있습니다.
이 어트리뷰트는 구조체 또는 열거형 선언에 적용하여 타입에 적용할 수 있는 변경 종류를 제한합니다. 이 속성은 라이브러리 evolution mode에서 컴파일할 때만 허용됩니다. 향후 버전의 라이브러리에서는 열거형의 케이스 또는 구조체의 저장된 인스턴스 프로퍼티를 추가, 제거 또는 재정렬하여 선언을 변경할 수 없습니다. 이러한 변경은 고정되지 않은 유형에서 허용되지만 고정된 유형에 대한 ABI 호환성이 손상됩니다.
라이브러리 evolution mode에서 고정되지 않은 구조체 및 열거형의 멤버와 상호 작용하는 코드는 라이브러리의 향후 버전이 해당 유형의 멤버 중 일부를 추가, 제거 또는 재정렬하는 경우에도 다시 컴파일하지 않고 계속 작업할 수 있는 방식으로 컴파일됩니다. 컴파일러는 런타임에 정보를 조회하고 간접 계층을 추가하는 등의 기술을 사용하여 이를 가능하게 합니다. 구조체나 열거형을 고정으로 표시하면 성능을 얻을 수 있는 유연성이 포기됩니다. 라이브러리의 향후 버전에서는 유형을 제한적으로만 변경할 수 있지만 컴파일러는 유형의 멤버와 상호 작용하는 코드에서 추가 최적화를 수행할 수 있습니다.
...어렵네?🤪
한 마디로 정리해보자면, @frozen
을 적용하면 해당 타입의 수정이 일어날 가능성을 배제하기 때문에 컴파일 시간을 줄여준다고 합니다. 열거형일 경우, switch문
에서 default
과정을 줄여주기 때문에 많이 사용된다고 하지만, 구조체는 주로 라이브러리 아니면 잘 사용되지 않는다고 합니다.
Wrapped
Wrapped
는 Generic 타입으로 명시되어 어느 타입이든 사용 가능한 범용 코드입니다.
ExpressibleByNilLiteral
Apple Developer - ExpressibleByNilLiteral에서 굉장히 간단하게 정리되어 있어서, 코드를 해부해보려 했지만 현재 나와있는 github에는 공개되지 않은 거 같습니다😅
nil
리터럴인nil
을 사용하여 초기화할 수 있는 타입입니다.
nil
은Swift
에서 값이 없다는 특별한 의미를 갖습니다.Optional
타입만ExpressibleByNilLiteral
을 따릅니다. 다른 목적으로nil
을 사용하는 타입에 대한ExpressibleByNilLiteral
준수는 권장되지 않습니다.
Optional
은 none
과 some(Wrapped)
으로 이루어진 열거형 타입입니다. 값이 존재한다면 some(Wrapped)
을 존재하지 않는다면 none
을 대입합니다.
정리하다보니, 엄청 길어져서 Optional
타입의 값을 추출하는 방법은 다음 포스트에서 다루겠습니다. 이렇게 개념을 딥하게 정리했지만, 간단하게 2문장으로 정리해보겠습니다 ㅎㅎ!
Optional
이란, 값이 있을 수도 있고 없을 수도 있다는 것을 표현해주는 열거형 타입입니다. 보통 변수안에 값이 정확히 있는지 없는지 확신할 수 없을 때에 많이 사용합니다.
ExpressibleByNilLiteral 이 어떤 코드인지 정말 궁금했는데 너무 아쉽네요 ㅠㅠ
정리를 너무 잘해주셔서 좋은 지식을 쏙쏙 얻어갑니다 감사합니다 🙌