<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=""><br class=""><div class=""><div><blockquote type="cite" class=""><div class="">On Oct 18, 2017, at 9:58 PM, Thorsten Seitz 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 dir="auto" class=""><div class=""></div><div class="">In your earlier emails you wrote</div><div class=""><br class=""></div><div class="">"<span style="background-color: rgba(255, 255, 255, 0);" class="">To make it concrete, say you write a function that just wraps map:</span></div><pre class=""><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">
func firstNames(ofPeople people: Sequence<Person>) -> Sequence<Person> {</span></font><span style="white-space: normal; background-color: rgba(255, 255, 255, 0); font-family: UICTFontTextStyleTallBody;" class=""> return people.map { $0.firstName }
} </span></pre><pre class=""><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class=""> I want that function to work on both ordered and unordered Sequences, and if you start with an ordered Sequence you should end up with an ordered Sequence. How do I make that work?"</span></font></pre><div class="">Your example _won't work even today_ as `map` _returns an Array_ and _not_ a Sequence, like I have written several times now including in the very email you have been answering.</div></div></div></blockquote><div><br class=""></div><div>I guess it wouldn’t work exactly as written because Sequence isn’t generic (why? I don’t know…)</div><div><br class=""></div><div>Something like this is closer to what I was trying to describe:</div><div><br class=""></div></div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div><div>func firstNames<SeqPerson>(ofPeople people:SeqPerson) -> AnySequence<String> where SeqPerson : Sequence, SeqPerson.Element : Person {<br class=""> return AnySequence(people.map { $0.firstName })<br class="">}</div></div></div></blockquote><div class=""><br class=""></div>(I shudder at how unnecessarily complex that is compared to .Net. I hope this can be improved in the future, or that I am missing something that would make it much simpler)<div class=""><br class=""></div><div class="">Since an array is a Sequence the (fixed) code above will work today with either an Array or Set or any other Sequence of Person objects, and its result can be fed into any function that takes in a Sequence of String.<br class=""><div class=""><div><br class=""><blockquote type="cite" class=""><div class=""><div dir="auto" class=""><div class="">So you would just write the method with the most general argument type which is required by the method:</div><div class=""><br class=""></div><div class="">func firstNames(ofPeople people: Iterable<Person>) -> [String] {</div><div class=""> <span style="background-color: rgba(255, 255, 255, 0);" class="">return people.map { $0.firstName }</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">}</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">The return type would still be Array _just like today_.</span></div></div></div></blockquote><div><br class=""></div><div>Let me be clearer: I want my method firstNames(ofPeople:) to work on sets just as it would work on any other Sequence. This method doesn’t care what order things are in, but it also doesn’t alter the order so it is suitable for use with both ordered and unordered inputs. Today I can write that method, and it will work for a set or an array or anything else that conforms to Sequence of Person, and it can then be chained with any other method that operates on a Sequence of Person.</div><div><br class=""></div><div>In order for your proposal to actually be effective you would need to change map so that it doesn’t always give an ordered result. That means you would have to make it not always return an array. The reason for that is that if you left map alone then you could end up writing code like this:</div><div><br class=""></div></div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div><div>var people:Set<Person> // comes from elsewhere</div><div>var names:[String] // comes from elsewhere</div><div>if (people.map { $0.firstName }.elementsEqual(names)) { // using the current name</div><div> // …</div><div>}</div></div></blockquote><div class=""><br class=""></div>Notice how you start with an unordered input, but then map gives you an array, which is ordered. Obviously map is useful to apply to sets so it would have to continue accepting whatever protocol Set conforms to. If it still returned Array regardless of the input type then it would convert an unordered input into an ordered output, and that loses all of the benefits you’re hoping to gain by having two types.<div class=""><br class=""></div><div class="">So clearly you would need map to not return Array when given an unordered input. It’s important that you understand this. Without changing the return type of map and other similar functions you have a huge hole in the type system that loses most of the benefits you’re going for. You may as well not do the feature if you’re not going to change this.</div><div class=""><br class=""></div><div class="">However, you also can’t just make map always return an unordered output type because then if you started with an ordered input you would get an unordered output, and that doesn’t make sense. That would be really tedious. So now you need two implementations of map: one that takes an unordered input and gives an unordered output, and another that takes an ordered input and returns an ordered output.</div><div class=""><br class=""></div><div class="">Kevin was suggesting that you could make this easier to deal with by introducing a new language feature, but it’s not clear exactly how that would work, and I’m not convinced it would actually solve the problem I’ve described.</div><div class=""><br class=""></div><div class="">This is what I mean when I said people weren’t thinking this all the way through. When you start to actually write out some code and thinking about how that code would work with the proposed split then things start to get a lot more complicated. It’s not just a matter of this one function. You have to think about which types other functions will take and produce, and you have to both avoid losing that new type information as well as avoid making simple code patterns much harder. I haven’t seen any clear explanation for how all of that can be satisfied.</div></div></body></html>