Swift

Optional에서의 map, flatMap

Phililip
728x90

안녕하세요.

 

Collection에서 flatMap은 많이 사용해봤는데... Optional에서도 map, flatMap을 사용할 수 있더라구요...? (저는 최근에 알았...)

 

그래서 이번에 Optional에서의 map, flatMap에 대해 알아볼게요.

 


 

## map

Optional에서의 map 함수는 Array나 Dictionary에서 사용하는 map 함수랑 약간 달라요.

 

공식 문서를 보면,

 

출처: https://developer.apple.com/documentation/swift/optional/map(_:)-7txtz

 

즉, 값이 nil일 경우 nil이 리턴되고, nil이 아닐 경우 클로저로 언래핑된 값을 전달해줘요.

 

(map을 직접 써보면 파라미터에 언래핑된 값이 전달되는 것을 알 수 있습니다.)

 

 

 

그럼 map을 언제 사용하냐??

Use the map method with a closure that returns a non-optional value.

 

클로저에서 non-optional 값을 리턴할 때 map을 사용합니다.

 

아래 코드를 볼까요??

let optionalInt: Int? = 10
let result = optionalInt.map { $0 + 1 }
print(result)  // Optional(11)

 

 

클로저에서 non-optional을 리턴 하지만 그 결과값은 optional 인 것을 알 수 있습니다.

 

 

 

그럼 클로저에서 optional 값을 리턴하는 것은 안될까요??

 

되긴 합니다. 되긴 합니다만.. 

 

예를 들어서 보여드릴게요.

let optionalInt: Int? = 10
let result1 = optionalInt.map { $0 + 1 }
let result2 = optionalInt.map { Optional($0 + 1) }
print(result1)  // Optional(11)
print(result2)  // Optional(Optional(11))

 

클로저에서 명시적으로 optional을 리턴하도록 했을 때.. 

 

result2의 타입은 ?? (Optional-Optional) 타입이 되기 때문에 non-optional을 리턴하는 경우에만 사용하라는 것이에요.

 

 

아하!!

 

즉, map을 사용하면 클로저의 리턴값을 명시적으로 Optional로 한번 더 감싸주는 것 같네요!!

 

 

이번엔 flatMap에 대해 살펴볼까요?

 

 

 

## flatMap

flatMap도 map과 동일하게 클로저로 넘어오는 파라미터는 언래핑되어서 전달되는 것이 보장됩니다.

 

 

Discussion을 살펴보면 map 하고 다른 부분이 있는데요.

Use the flatMap method with a closure that returns an optional value.

 

map과는 다르게 클로저에서 optional을 리턴할 때 flatMap을 사용하라고 합니다.

 

위에서 사용한 예시를 그대로 flatMap으로만 바꾸고 결과값을 한번 볼게요.

let optionalInt: Int? = 10
let result1 = optionalInt.flatMap { $0 + 1 }
let result2 = optionalInt.flatMap { Optional($0 + 1) }
print(result1)  // Optional(11)
print(result2)  // Optional(11)

 

 

오홓...

 

클로저에서 optional을 리턴해도 flatMap의 결과값은 그냥 Optional 이군요.

 

그럼... flatMap은 어떤 규칙으로 리턴 값 & 타입이 결정되는 것일까요?

 

제가 flatMap의 구현부를 볼 수 없으니... 여러가지 테스트를 해봤어요.

let optionalInt: Int? = 10
let result1 = optionalInt.flatMap { Optional(Optional($0 + 1)) }  // Optional(Optional(11))
let result2 = optionalInt.flatMap { [$0] }  // Optional([10])
let result3 = optionalInt.flatMap { [Optional($0)] }  // Optional([Optional(10)])
let result4 = optionalInt.flatMap { Optional([$0]) }  // Optional([10])
let result5 = optionalInt.flatMap { Optional([Optional($0)]) }  // Optional([Optional(10)])

 

여기서 나온 결론은,

 

flatMap을 사용하면 클로저의 리턴값을 언래핑한 후에 그걸 다시 Optional로 래핑해주는 것 아닐까 싶어요.

(혹시 더 자세하게 아시는 분 계시면 알려주세요ㅠㅠ)

 

 

 

 

## 참고

- https://developer.apple.com/documentation/swift/optional

- https://developer.apple.com/documentation/swift/optional/map(_:)-7txtz

- https://developer.apple.com/documentation/swift/optional/flatmap(_:) 

 


 

이번 글은 여기서 마무리.

 

 

 

반응형

'Swift' 카테고리의 다른 글

mutating  (1) 2022.12.18
@autoclosure  (2) 2022.12.15
@inlinable, @usableFromInline  (0) 2022.08.15
[Swift 5.7] if let shorthand  (0) 2022.07.05
inout  (0) 2022.06.05