[swift-evolution] [Review] SE-0187: Introduce Sequence.filterMap(_:)

Paul Cantrell cantrell at pobox.com
Wed Nov 8 23:29:06 CST 2017


> What is your evaluation of the proposal?

Strong approve.

I would happily also accept name variants such as mapFilter — but I’m heartily in favor of _something_ that distinguishes _by name_ flattening sequences vs. filtering nils.

> Is the problem being addressed significant enough to warrant a change to Swift?

The existing overloading of “flatMap” is not just confusing; it actively defeats some of the usefulness of Swift’s type checking. The proposal’s examples demonstrate this with the string example, but there’s another scenario (I think more compelling) that the proposal doesn’t mention. Consider this innocent-looking code:

    struct Doodad {
        public var words: [String]
    }

    // Meanwhile, elsewhere:

    let doodads = [
        Doodad(words: ["Some", "people", "like", "mustard"]),
        Doodad(words: ["even", "on", "custard"])
    ]

    let wordCount = doodads.flatMap { $0.words }.count

This counts 7 words, as expected. But if we make words optional, leaving the rest of the code unaltered:

        public var words: [String]?

…then suddenly wordCount changes to 2. Under the proposal, this would at least generate a deprecation warning.

Developing in Swift, I have the general expectation that if I make something optional, the type checker will help me discover the places where I need to deal with that change. Here it does not; instead, it silently changes the semantics of my existing code.

Note that the problem here has nothing to do with optional hoisting. If I understand correctly — and please do correct me if I’m wrong! — Kevin’s proposed alternative to flag unintended hoisting would not help solve this at all.

The problem here has instead to do with the fact that in programming languages, names serve as proxies for developer intent. That is, when we type, say, count, we are not just providing a human-readable GUID for a piece of code; we are implicitly referencing some mental model, some shared understanding of what that code we’re invoking is supposed to do. “Give me the count; we all know what that means, right?”

The fact that names capture developer intent is why static type checkers can help us reason about our code. Type systems catch developer errors because they can check a developer’s understanding of what they’re doing against the code’s own formal description of what it actually does (or at least some aspects thereof). If I write someOptionalVar.count, the compile error don’t just mean “that type doesn’t have that member;” it means something deeper and more useful: “You intend to count items, but that could be nil; how should I count nil? That code doesn’t mean what you think it means.”

The problem in the Doodads example is that the name flatMap is used to identify two distinct intents: concatenating arrays and filtering nils. One can argue that those two operations are, in some lofty abstract sense, if you squint, two instances of some more general pattern — but I don’t think it’s fair to say that they represent the same intent. These separate intents deserve separate names.

I don’t mean that we should take this to its absurd logical extreme and ensure that all method names are globally unique across the whole stdlib. But in this case, it doesn’t pay to intentionally create a name collision in a place where confusion is likely and the results mistakes are prone to going undetected. This overloading of flatMap has always bugged me, and I’d be pleased to see it cleaned up.

> Does this proposal fit well with the feel and direction of Swift?

Clarity at the point of use and type safety are lynchpins of the language’s philosophy, yes.

> If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

Other languages I’ve used don’t conflate sequences and optionals the way Swift’s flatMap does. This proposal brings Swift into line with general convention.

> How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

A little light reading and too much writing.

Cheers, P



> On Nov 7, 2017, at 5:23 PM, John McCall via swift-evolution <swift-evolution at swift.org> wrote:
> 
> Hello, Swift community!
> 
> The review of "SE-0187: Introduce Sequence.filterMap(_:)" begins now and runs through November 14th, 2017.  The proposal is available here:
> 
> https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md <https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md>
> 
> Reviews are an important part of the Swift evolution process.  All reviews should be sent to the swift-evolution mailing list at
> 
> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
> or, if you would like to keep your feedback private, directly to me as the review manager.  When replying, please try to keep the proposal link at the top of the message:
> 
> Proposal link:
> 
> https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md <https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md>
> Reply text
> Other replies
> What goes into a review?
> 
> The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift.
> 
> When writing your review, here are some questions you might want to answer in your review:
> 
> 	• What is your evaluation of the proposal?
> 	• Is the problem being addressed significant enough to warrant a change to Swift?
> 	• Does this proposal fit well with the feel and direction of Swift?
> 	• If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
> 	• How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
> 
> More information about the Swift evolution process is available at:
> 
> https://github.com/apple/swift-evolution/blob/master/process.md <https://github.com/apple/swift-evolution/blob/master/process.md>
> 
> As always, thank you for contributing to the evolution of Swift.
> 
> John McCall
> Review Manager
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20171108/d53a800c/attachment.html>


More information about the swift-evolution mailing list