Avatar
omochimetaru 1/9/2018 6:36 AM
えっとまず
6:36 AM
struct Cat { var age: Int = 3 var name: String = "mike" } var cats = [Cat.init(), Cat(), Cat()] let x = cats.flatMap { $0.age } print(x)
6:36 AM
[3, 3, 3]
6:36 AM
これがコンパイルが通っちゃうのが微妙だよね、という話があります
6:37 AM
これは、プログラマーが意図していたコードは正しくは、 cats.map { $0.age } です。
6:37 AM
String から Optional<String> への暗黙変換が発生するせいで、flatMap でも動いてしまっているんだけど、
6:37 AM
実際には全部の要素が .some(String) になっているので、flatMapにする意味がなくって、mapにするべき、という例です。
6:38 AM
で、Swift4でStringがcollectionになっちゃったことによって・・・
6:38 AM
let y = cats.flatMap { $0.name } print(y)
6:38 AM
["m", "i", "k", "e", "m", "i", "k", "e", "m", "i", "k", "e"]
6:38 AM
同じ間違いを、 $0.age じゃなくて、 $0.name で行った場合
6:38 AM
↑のようにもっと悲惨な事になります。
6:39 AM
今度はこれは何が起きてるかっていうと、Collectionを返す関数をflatMap しているので、正しく flatten されてしまっていて
6:39 AM
["mike", "mike", "mike"] になってほしかったのが
6:39 AM
"mike" が ["m", "i", "k", "e"] とみなされて、二重配列がflattenされる挙動になっちゃった。
6:40 AM
想定してるのが「mapしたいのに間違ってflatMap書いちゃった」シナリオだから、
6:40 AM
挙動すらぶっ壊れたってことですね
6:42 AM
で、この問題は、flatMapが受け付けるクロージャが T->[U] と T->U? の2種類のオーバーロードがあることによって、 全てがややこしくなってるから、 後者の T->U? を受け付けるflatMapはcompactMapに名前を変えることにした。
👏🏻 2
😍 2