[swift-users] Swift 4 Strings and flatMap

Santiago Gil santi at thumbtack.com
Mon Oct 23 16:03:30 CDT 2017


The object we were using flatMap on used to be optional. The fix was to use
a map instead since it was no longer needed to be flatMapped. I agree that
this would be a mis-use of flatMap but the inference behaviour here is
still unexpected.

If the compiler doesn't support multi-statement closure type inference it
would be nice for it to warn or error out in cases like this to enforce
type, or it can also be handled by a linter/static analysis.

- Santiago

On Sat, Oct 21, 2017 at 12:39 PM Martin R <martinr448 at gmail.com> wrote:

> Compare  https://bugs.swift.org/browse/SR-1570 : Swift can infer the
> return type from single-statement closures, but not from multi-statement
> closures. Therefore in
>
>     let result = strArr.flatMap { x in
>         return x
>     }
>
> the closure type is inferred as (String)-> String, and therefore the
> flatMap call matches exactly the
>
>    func flatMap<SegmentOfResult>(_ transform: (Self.Element) throws ->
> SegmentOfResult) rethrows -> [SegmentOfResult.Element]
>    where SegmentOfResult : Sequence
>
> Sequence method, with Self.Element == String and SegmentOfResult ==
> String, and flatMap returns [SegmentOfResult.Element] == [Character].
>
> In
>
>     let result = strArr.flatMap { x in
>         print(x)
>         return x
>     }
>
> the closure return type is not inferred from the closure itself, because
> it is a multi-statement closure. Here the compiler (apparently) chooses the
>
>     public func flatMap(_ transform: (Element) throws -> String?) rethrows
> -> [String]
>
> Array method, and promotes `String` to `String?`. You would get the same
> result with an explicit return type in the single-statement closure:
>
>     let result = strArr.flatMap { x -> String? in
>         return x
>     }
>
> But why do you use flatMap at all? If the intention is to map [String] to
> [String] then map() would be the right method:
>
>     let strArr = ["Hi", "hello"]
>     let result: [String] = strArr.map { x in
>         return x
>     }
>     print(result) // ["Hi", "hello"]
>
> Regards, Martin
>
>
> > On 21. Oct 2017, at 02:50, Santiago Gil via swift-users <
> swift-users at swift.org> wrote:
> >
> > Hi Swift users,
> >
> > I just ran into a bug after a Swift 4 migration where we expected
> [String] and got [Character] from a flatMap since flatMap will flatten the
> String since it's now a collection.  While I understand why flatMap behaves
> this way now that string are collections, in testing this I found some
> weird behaviour...
> >
> > var strArr = ["Hi", "hello"]
> >
> > let result = strArr.flatMap { x in
> >
> >     return x
> >
> > }
> >
> >
> > The type of results ends up being [Character] in the above case.
> However, adding a print statement changes things.
> >
> >
> > var strArr = ["Hi", "hello"]
> >
> > let result = strArr.flatMap { x in
> >
> >     print(x)
> >
> >     return x
> >
> > }
> >
> > In this case, result is of type [String]
> >
> > This seems like a bug, or is this expected Swift behaviour?
> >
> > Thanks,
> >
> > Santiago
> >
> > _______________________________________________
> > swift-users mailing list
> > swift-users at swift.org
> > https://lists.swift.org/mailman/listinfo/swift-users
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20171023/dd94d750/attachment.html>


More information about the swift-users mailing list