🍎

[Swift] flatMapのメモ

に公開1

はじめに

バイトでSwiftを使っているんですけど、そこでflatMapというものを初めて知りました。
それで少し勉強したんですけど、きちんと理解していないところもあるので、もう少し勉強してみてそれをメモおこうと思います!

Optional.flatMapとは?

Optional.flatMapとは、変数がnilならそのままnilを返し、そうでなければそのクロージャを実行して値を返すというものです。

よく、クロージャの中では変数を非オプショナル型として扱う必要があるときに使われることが多いです。

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

Optional.flatMapの使い方

それでは、どのように使うのかを実際に例を出して紹介してみます。

まずは以下のような関数を用意します。

func calc(num: Int) -> Int {
    num * 2
}

この関数は、非オプショナル型(Int型)の引数を受け取り、その値を2倍にして返します。

次に、以下のようなオプショナル型の変数を定義します。

let num: Int? = 5

この変数をそのままcalc関数に渡して

let result = calc(num: num)

とすると

Value of optional type 'Int?' must be unwrapped to a value of type 'Int'

とエラーが出ます。

エラーについて

このエラーはcalc関数が非オプショナル型(Int型)を引数に取るのに対し、numがオプショナル型(Int?型)であるので型が一致しないというものです。
Swiftでは、オプショナル型をそのまま非オプショナル型の引数に渡すことはできません。

この程度なら、例えば

let result = calc(num: num ?? 0)

にして実行できますが、これではresultnilであることを検知することができません。
できればnumnilの時はresultnilにしたいですよね。

その場合に便利なのがflatMapです。

let result: Int? = num.flatMap{ calc(num: $0) }

このコードでは、flatMapを使うことで以下の動作を実現しています:

  1. numnilの場合、クロージャは実行されず、resultにはnilが渡されます。
  2. numnilでない場合、calc関数が実行され、その返り値がresultに渡されます。

このように、flatMapを使うことで、オプショナル型を安全にアンラップしつつ、クロージャ内で処理を行うことができます。

Array.flatMapとは?

swift flatMapとかで検索していると、配列バージョンのArray.flatMapも出てきます。

このメソッドは、要素を変換しつつ、ネストされた配列を一次元配列に変換することができます。
例えば、

let array: [[Int]] = [
    [1, 2, 3],
    [4, 5],
    [6, 7, 8],
    [],
    [9]
]

let flatArray = array.flatMap { $0 }

で、以下のような一次元配列になります。

[1, 2, 3, 4, 5, 6, 7, 8, 9]

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

このように、今回のテーマであるOptional.flatMapArray.flatMapは名前こそ似ているものの、全然違うものなので、注意してください!

さいごに

今回は、Optional.flatMapについての記事を書きました。
バイトをしているときに知って試しに調べてみたものですが、思ったよりも便利なメソッドだったので調べて良かったなと思います。

まだまだSwiftは勉強中ですが、これからもいろいろ勉強していきます!

GitHubで編集を提案

Discussion

Masaki HoriMasaki Hori

この場合はOptional.mapを使うのが適切です。