<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><blockquote type="cite" class="">What is your evaluation of the proposal?<br class=""></blockquote><br class=""><div class="">Strong approve.</div><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class="">Is the problem being addressed significant enough to warrant a change to Swift?<br class=""></blockquote><br class=""></div><div class="">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:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255);" class=""><div style="font-family: Menlo; font-size: 11px; margin: 0px; font-stretch: normal; line-height: normal;" class=""> <span style="color: #323e7d" class="">struct</span> Doodad {</div><div style="font-family: Menlo; font-size: 11px; margin: 0px; font-stretch: normal; line-height: normal;" class=""> <span style="color: #323e7d" class="">public</span> <span style="color: #323e7d" class="">var</span> words: [<span style="color: #587ea8" class="">String</span>]</div><div style="font-family: Menlo; font-size: 11px; margin: 0px; font-stretch: normal; line-height: normal;" class=""> }</div><div style="font-family: Menlo; font-size: 11px; margin: 0px; font-stretch: normal; line-height: normal;" class=""><br class=""></div><div style="font-family: Menlo; font-size: 11px; margin: 0px; font-stretch: normal; line-height: normal;" class=""> <span style="color: rgb(102, 139, 73);" class="">// Meanwhile, elsewhere:</span></div><div style="font-family: Helvetica; font-size: 12px; margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="font-family: Menlo; font-size: 11px; margin: 0px; font-stretch: normal; line-height: normal;" class=""> <span style="color: #323e7d" class="">let</span> doodads = [</div><div style="font-family: Menlo; font-size: 11px; margin: 0px; font-stretch: normal; line-height: normal; color: rgb(133, 62, 100);" class=""><span style="color: #000000" class=""> </span><span style="color: #587ea8" class="">Doodad</span><span style="color: #000000" class="">(words: [</span>"Some"<span style="color: #000000" class="">, </span>"people"<span style="color: #000000" class="">, </span>"like"<span style="color: #000000" class="">, </span>"mustard"<span style="color: #000000" class="">]),</span></div><div style="font-family: Menlo; font-size: 11px; margin: 0px; font-stretch: normal; line-height: normal;" class=""> <span style="color: #587ea8" class="">Doodad</span>(words: [<span style="color: #853e64" class="">"even"</span>, <span style="color: #853e64" class="">"on"</span>, <span style="color: #853e64" class="">"custard"</span>])</div><div style="font-family: Menlo; font-size: 11px; margin: 0px; font-stretch: normal; line-height: normal;" class=""> ]</div><div style="font-family: Menlo; font-size: 11px; margin: 0px; font-stretch: normal; line-height: normal;" class=""><br class=""></div><div style="font-family: Menlo; font-size: 11px; margin: 0px; font-stretch: normal; line-height: normal;" class=""> <span style="color: #323e7d" class="">let</span> wordCount = doodads.<span style="color: #587ea8" class="">flatMap</span> { $0.<span style="color: #587ea8" class="">words</span> }.<span style="color: #587ea8" class="">count</span></div><div style="font-family: Menlo; font-size: 11px;" class=""><span style="font-family: "Helvetica Neue"; font-size: 13px;" class=""><br class=""></span></div><div style="font-family: Menlo; font-size: 11px;" class=""><span style="font-family: "Helvetica Neue"; font-size: 13px;" class="">This counts 7 words, as expected. But if we make </span>words<span style="font-family: "Helvetica Neue"; font-size: 13px;" class=""> optional, leaving the rest of the code unaltered:</span></div><div style="font-family: Menlo; font-size: 11px;" class=""><span style="font-family: "Helvetica Neue"; font-size: 13px;" class=""><br class=""></span></div><div style="font-family: Menlo; font-size: 11px;" class=""><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""> <span style="color: #323e7d" class="">public</span> <span style="color: #323e7d" class="">var</span> words: [<span style="color: #587ea8" class="">String</span>]?</div></div><div style="font-family: Menlo; font-size: 11px;" class=""><span style="font-family: "Helvetica Neue"; font-size: 13px;" class=""><br class=""></span></div><div style="font-family: Menlo; font-size: 11px;" class=""><span style="font-family: "Helvetica Neue"; font-size: 13px;" class="">…then suddenly </span>wordCount<span style="font-family: "Helvetica Neue"; font-size: 13px;" class=""> changes to 2. Under the proposal, this would at least generate a deprecation warning.</span></div><div style="font-family: Menlo; font-size: 11px;" class=""><span style="font-family: "Helvetica Neue"; font-size: 13px;" class=""><br class=""></span></div><div style="font-family: Menlo; font-size: 11px;" class=""><span style="font-family: "Helvetica Neue"; font-size: 13px;" class="">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.</span></div><div style="font-family: Menlo; font-size: 11px;" class=""><span style="font-family: "Helvetica Neue"; font-size: 13px;" class=""><br class=""></span></div><div class=""><span style="font-family: "Helvetica Neue"; font-size: 13px;" class="">Note that the problem here </span><b style="font-family: "Helvetica Neue"; font-size: 13px;" class="">has nothing to do with optional hoisting.</b> If I understand correctly — and please do correct me if I’m wrong! — Kevin’s <span style="font-family: "Helvetica Neue"; font-size: 13px;" class="">proposed alternative to flag unintended hoisting would not help solve this at all.</span></div><div style="font-family: Menlo; font-size: 11px;" class=""><span style="font-family: "Helvetica Neue"; font-size: 13px;" class=""><br class=""></span></div><div class=""><span style="font-family: "Helvetica Neue"; font-size: 13px;" class="">The problem here has instead to do with the fact that in programming languages, <b class="">names serve as proxies for developer intent</b>. That is, when we type, say,</span><span style="font-family: "Helvetica Neue"; font-size: 13px;" class=""> </span><span style="font-family: Menlo; font-size: 11px; color: rgb(88, 126, 168);" class="">count</span>, 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?”</div><div style="font-family: Menlo; font-size: 11px;" class=""><span style="font-family: "Helvetica Neue"; font-size: 13px;" class=""><br class=""></span></div><div class="">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 <i class="">understanding</i> of what they’re doing against the code’s own <i class="">formal description</i> of what it actually does (or at least some aspects thereof). If I write <span style="font-family: Menlo; font-size: 11px;" class="">someOptionalVar.</span><span style="color: rgb(88, 126, 168); font-family: Menlo; font-size: 11px;" class="">count</span>, 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.”</div><div class=""><br class=""></div><div class="">The problem in the Doodads example is that <b class="">the name <span style="color: rgb(88, 126, 168); font-family: Menlo; font-size: 11px;" class="">flatMap</span> is used to identify two distinct intents</b>: 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 <i class="">intent</i>. These separate intents deserve separate names.</div><div class=""><br class=""></div><div class="">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.</div></div></div><div><br class=""></div><div><blockquote type="cite" class="">Does this proposal fit well with the feel and direction of Swift?<br class=""></blockquote><div><br class=""></div><div>Clarity at the point of use and type safety are lynchpins of the language’s philosophy, yes.</div><br class=""><blockquote type="cite" class="">If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?<br class=""></blockquote><div><br class=""></div><div>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.</div><br class=""><blockquote type="cite" class="">How much effort did you put into your review? A glance, a quick reading, or an in-depth study?<br class=""></blockquote><br class=""></div><div>A little light reading and too much writing.</div><div><br class=""></div><div>Cheers, P</div><div><br class=""></div><div><br class=""></div><div><br class=""><blockquote type="cite" class=""><div class="">On Nov 7, 2017, at 5:23 PM, John McCall via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Hello, Swift community!<div class=""><br class=""></div><div class="">The review of "SE-0187: Introduce Sequence.filterMap(_:)" begins now and runs through November 14th, 2017. The proposal is available here:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><a href="https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md" class="">https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md</a></div></blockquote><div class=""><br class=""></div><div class="">Reviews are an important part of the Swift evolution process. All reviews should be sent to the swift-evolution mailing list at</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></blockquote><br class="">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 class=""><br class=""><blockquote class="" 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 class="" 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 class="" 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" class=""><a href="https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md" class="">https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md</a></font></blockquote></blockquote><blockquote class="" 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 class="" style="box-sizing: border-box; margin-top: 0px; margin-bottom: 0px;">Reply text</div></blockquote><blockquote class="" 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 class="" 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 class="" style="box-sizing: border-box; margin-top: 0px; margin-bottom: 0px;">Other replies</div></blockquote></blockquote><b class="">What goes into a review?</b><br class=""><br class="">The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift.<div class=""><br class=""></div><div class="">When writing your review, here are some questions you might want to answer in your review:<br class=""><br class=""><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>• What is your evaluation of the proposal?<br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>• Is the problem being addressed significant enough to warrant a change to Swift?<br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>• Does this proposal fit well with the feel and direction of Swift?<br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>• If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?<br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>• How much effort did you put into your review? A glance, a quick reading, or an in-depth study?<br class=""></div><div class=""><br class=""></div>More information about the Swift evolution process is available at:<div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><a href="https://github.com/apple/swift-evolution/blob/master/process.md" class="">https://github.com/apple/swift-evolution/blob/master/process.md</a></div></blockquote><div class=""><br class="">As always, thank you for contributing to the evolution of Swift.<br class=""><br class="">John McCall<br class="">Review Manager<br class=""></div></div></div>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></div></body></html>