<div dir="ltr"><div>I’ll put my vote in for `filterMap`!</div><div><br></div><div>I’d like to call out some fun properties and generalizations that `filterMap` has that might give a little more credence to why it should be called this.</div><div><br></div><div>There is a very natural way of bridging the worlds of optionals and booleans. In fact, considering that `Bool` is the unique type with two elements, we could even define `typealias Bool = Void?`, where `Void()` is true and `nil` is false! Though I am definitely not advocating that!</div><div><br></div><div>Given that perspective, there is then also a natural way of lifting predicates `(A) -> Bool` to the world of functions that `filterMap` understands:</div><div><br></div><div>```</div><div><div>func optionalBool<A>(_ p: @escaping (A) -> Bool) -> (A) -> A? {</div><div> return { p($0) ? .some($0) : nil }</div><div>}</div></div><div>```</div><div><br></div><div>Given such a function, then `filter` on arrays is nothing but `filterMap(optionalBool(p))`!</div><div><br></div><div>The really exciting part is then to take note that the highly contested and dreaded `Either<A, B>` is just a generalization of `Optional<B>`, in that we model the absence of `B` by providing a value of type `A`. Given that observation, what does the filter/filterMap story look like for `Either`s? Why that’s none other than `partition` and `partitionMap`! These are functions that allow you to partition an array into two subsets. The first one doesn’t change the wrapped value of the array (much like `filter`) but the second allows providing an additional mapping function. Here’s how they might look:</div><div><br></div><div>```</div><div><div>func _partitionMap<A, B>(_ p: @escaping (Element) -> Either<A, B>) -> (left: [A], right: [B]) {</div><div> var result = (left: [A](), right: [B]())</div><div> for x in self {</div><div> switch p(x) {</div><div> case let .left(a):</div><div> result.left.append(a)</div><div> case let .right(b):</div><div> result.right.append(b)</div><div> }</div><div> }</div><div> return result</div><div>}</div><div><br></div><div>func _partition(_ p: @escaping (Element) -> Bool) -> (`true`: Array, `false`: Array) {</div><div> // Can easily define `_partition` in terms of `_partitionMap`!</div><div> return _partitionMap(eitherBool(p))<br></div><div>}</div></div><div>```</div><div><br></div><div>The things that are nice about this:</div><div><br></div><div>* Builds on a few foundational, atomic ideas.</div><div>* Shows that there are future generalizations that we might not even be thinking about right now</div><div>* Allows one to see the shadows of simpler constructions (e.g. filter/partition) from the more complex constructions (e.g. filterMap/partitionMap)</div><div><br></div><div>I will conclude that I 100% am not advocating for us to bring in `Either` and `optionalBool` and `eitherBool` and all that wildness. I simply want to show that there are some wonderful ideas lurking behind these names, and so it’d be nice to not hide them with overly specific and overly descriptive names.</div><div><br></div><div>If anyone wants to play with these functions I have put them in a gist:</div><div><br></div><div><a href="https://gist.github.com/mbrandonw/7aab415312379022e60f3a9a107b6792">https://gist.github.com/mbrandonw/7aab415312379022e60f3a9a107b6792</a><br></div><div><br></div><div><br></div><br><br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word;line-break:after-white-space"><div><blockquote type="cite"><div><div style="word-wrap:break-word;line-break:after-white-space"><div><blockquote type="cite"><div>On Nov 15, 2017, at 12:55 PM, John McCall via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:</div><br class="m_-2996687654117919175Apple-interchange-newline"><div><div style="word-wrap:break-word">Hello, Swift Community!<div><br></div><div>The initial review of "SE-0187: Introduce Sequence.filterMap(_:)" ran through yesterday, November 14th, 2017. The proposal is available here:</div><div><br></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><a href="https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md" target="_blank">https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md</a></div></blockquote><div><br></div><div>There was a significant amount of discussion, and people came down with reasonable arguments both for and against the proposal. After reviewing that feedback, the core team feels that the central question is whether Swift benefits from overloading flatMap in this way. There is a reasonable argument that an Optional is a sort of container, and therefore it makes sense to "flatten" that container into a surrounding container. But Swift has resisted applying that interpretation in its library design; for example, you cannot directly iterate an Optional or append its contents to an Array. In general, we feel that using different operations for working with Optionals tends to make code easier to both write and understand, especially given the existence of implicit optional promotion, which we cannot eliminate or easily suppress based on the context. On reflection, we think it was a mistake to use the same name in the first place, and there is no better time to fix a mistake than now.</div><div><br></div><div>While we accept that this will cause some amount of "code churn" for developers when they adopt Swift 5, the required change is a simple rename that should be painless to automatically migrate. Of course, sample code on the internet will become obsolete, but fix-its will easily update that code if pasted into a project, and the samples themselves (once corrected) should become clearer and easier to teach after this change, as is generally true when overloading is removed.</div><div><br></div><div>Accordingly, SE-0187 is <b>accepted</b>, at least as far as not calling the operation "flatMap". We are re-opening the review until next Monday, November 20th, 2017, in order to have a focused discussion about the new name. Names that seemed to gain some traction in the first review include:</div><div><br></div><div> - filterMap, which has precedent in existing functional languages, as well as some popular Swift libraries, but which some people view as confusing</div><div><br></div><div> - compactMap, which builds off the precedent of "compact" in Ruby</div><div><br></div><div>But please feel free to suggest a name other than these.</div><div><br></div><div><b>Reviews</b></div><div><br></div><div><div>Reviews are an important part of the Swift evolution process. All reviews should be sent to the swift-evolution mailing list at</div><div><br></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a></blockquote><br>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:<br><br><blockquote style="box-sizing:border-box;margin:0px 0px 16px;padding:0px 1em;border-left-width:0.25em;border-left-style:solid;border-left-color:rgb(223,226,229);background-color:rgb(255,255,255)"><p style="color:rgb(106,115,125);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;box-sizing:border-box;margin-top:0px;margin-bottom:16px">Proposal link:</p><blockquote style="box-sizing:border-box;margin:0px;padding:0px 1em;border-left-width:0.25em;border-left-style:solid;border-left-color:rgb(223,226,229)"><font size="3"><a href="https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md" target="_blank">https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md</a></font></blockquote></blockquote><blockquote style="box-sizing:border-box;margin:0px 0px 16px;padding:0px 1em;color:rgb(106,115,125);border-left-width:0.25em;border-left-style:solid;border-left-color:rgb(223,226,229);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)"><div style="box-sizing:border-box;margin-top:0px;margin-bottom:0px">Reply text</div></blockquote><blockquote style="box-sizing:border-box;margin:0px 0px 16px;padding:0px 1em;color:rgb(106,115,125);border-left-width:0.25em;border-left-style:solid;border-left-color:rgb(223,226,229);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)"><blockquote style="box-sizing:border-box;margin:0px;padding:0px 1em;border-left-width:0.25em;border-left-style:solid;border-left-color:rgb(223,226,229)"><div style="box-sizing:border-box;margin-top:0px;margin-bottom:0px">Other replies</div></blockquote></blockquote><b>What goes into a review?</b><br><br>The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift.<div><br></div><div>When writing your review, here are some questions you might want to answer in your review:<br><br><div><span class="m_-2996687654117919175Apple-tab-span" style="white-space:pre-wrap">        </span>• What is your evaluation of the proposal?<br></div><div><span class="m_-2996687654117919175Apple-tab-span" style="white-space:pre-wrap">        </span>• Is the problem being addressed significant enough to warrant a change to Swift?<br></div><div><span class="m_-2996687654117919175Apple-tab-span" style="white-space:pre-wrap">        </span>• Does this proposal fit well with the feel and direction of Swift?<br></div><div><span class="m_-2996687654117919175Apple-tab-span" style="white-space:pre-wrap">        </span>• If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?<br></div><div><span class="m_-2996687654117919175Apple-tab-span" style="white-space:pre-wrap">        </span>• How much effort did you put into your review? A glance, a quick reading, or an in-depth study?<br></div><div><br></div>More information about the Swift evolution process is available at:<div><br></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><a href="https://github.com/apple/swift-evolution/blob/master/process.md" target="_blank">https://github.com/apple/swift-evolution/blob/master/process.md</a></div></blockquote><div><br>As always, thank you for contributing to the evolution of Swift.<br><br>John McCall<br>Review Manager</div></div></div></div></div></blockquote></div></div></div></blockquote></div></div><div style="word-wrap:break-word;line-break:after-white-space"><div><blockquote type="cite"><div><div style="word-wrap:break-word;line-break:after-white-space"><div><blockquote type="cite"><div>_______________________________________________<br>swift-evolution mailing list<br><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br></div></blockquote></div></div></div></blockquote></div></div><div style="word-wrap:break-word;line-break:after-white-space"><div><blockquote type="cite"><div>_______________________________________________<br>swift-evolution mailing list<br><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br></div></blockquote></div></div>_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
</blockquote></div></div>