<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div><br><br>Sent from my iPad</div><div><br>On Jan 22, 2017, at 11:25 AM, Karim Nassar &lt;<a href="mailto:karim@karimnassar.com">karim@karimnassar.com</a>&gt; wrote:<br><br></div><blockquote type="cite"><meta http-equiv="Content-Type" content="text/html charset=utf-8"><div><blockquote type="cite" class=""><div class=""><div class="">From: Dave Abrahams &lt;<a href="mailto:dabrahams@apple.com" class="">dabrahams@apple.com</a>&gt;<br class="">To: Brent Royal-Gordon &lt;<a href="mailto:brent@architechies.com" class="">brent@architechies.com</a>&gt;</div></div></blockquote><blockquote type="cite" class=""><br class=""></blockquote><blockquote type="cite" class=""><div class=""><div class=""><blockquote type="cite" class="">While it's great that `compared(to:case:etc.)` is parallel to `compared(to:)`, you don't actually want to *use* anything like `compared(to:)` if you can help it. Think about the clarity at the use site:<br class=""><br class=""> &nbsp;&nbsp;if foo.compared(to: bar, case: .insensitive, locale: .current) == .before { … }<br class=""></blockquote><br class="">Right. &nbsp;We intend to keep the usual comparison operators.<br class=""><br class="">Poor readability of "foo &lt;=&gt; bar == .before" is another reason we think that giving up on "&lt;=&gt;" is no great loss.<br class=""><br class=""><blockquote type="cite" class="">The operands and sense of the comparison are kind of lost in all this garbage. You really want to see `foo &lt; bar` in this code somewhere, but you don't.<br class=""></blockquote><br class="">Yeah, we thought about trying to build a DSL for that, but failed. &nbsp;I think the best possible option would be something like:<br class=""><br class=""> &nbsp;foo.comparison(case: .insensitive, locale: .current) &lt; bar<br class=""><br class="">The biggest problem is that you can build things like<br class=""><br class=""> &nbsp;&nbsp;&nbsp;fu = foo.comparison(case: .insensitive, locale: .current)<br class=""> &nbsp;&nbsp;&nbsp;br = bar.comparison(case: .sensitive)<br class=""> &nbsp;&nbsp;&nbsp;fu &lt; br // what does this mean?<br class=""><br class="">We could even prevent such nonsense from compiling, but the cost in library API surface area is quite large.<br class=""><br class=""><blockquote type="cite" class="">I'm struggling a little with the naming and syntax, but as a general approach, I think we want people to use something more like this:<br class=""><br class=""> &nbsp;&nbsp;if StringOptions(case: .insensitive, locale: .current).compare(foo &lt; bar) { … }<br class=""></blockquote><br class="">Yeah, we can't do that without making <br class=""><br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let a = foo &lt; bar<br class=""><br class="">ambiguous<br class=""></div></div></blockquote></div><br class=""><div class=""><br class=""></div><div class="">So, cue crazy idea #1, but what about something like this?</div><div class=""><br class=""></div><div class=""><font face="Menlo" class="">struct StringComparison {</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let leftHand: String</font></div><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let rightHand: String</font></div><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let comparison: SortOrder</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>var insensitive: Bool {</font></div><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">                </span>...</font></div><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}</font></div><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>//&nbsp;… etc</font></div><div class=""><font face="Menlo" class="">}</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">func &lt;(lhs: String, rhs: String) -&gt; StringComparison { // similar for ==, &gt;, etc.</font></div><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>return StringComparison(leftHand: lhs, rightHand: rhs, comparison: .before)</font></div><div class=""><font face="Menlo" class="">}</font></div><div class=""><div class=""><br class=""></div></div><div class="">Then:</div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><br class=""></div></blockquote><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>if (a &lt; b).insensitive {<br class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>...<br class=""></font><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}</font></div><div class=""><br class=""></div><div class="">This would fix the ambiguity of:</div><div class=""><br class=""></div><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let a = foo &lt; bar //&nbsp;‘a' is StringComparison</font></div><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>if a.insensitive {</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}</font></div><div class=""><br class=""></div><div class="">IMHO, the big problem with this is that the most obvious default case really should fall-through to a boolean value for the comparison struct:</div><div class=""><br class=""></div><div class=""><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>if a &lt; b { // case-sensitive, non-localized compare</font></div><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>...</font></div><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}</font></div></div><div class=""><br class=""></div><div class="">...but I can’t figure out how to make that work without the old BooleanType protocol, maybe someone smarter than I could…</div></blockquote><br><div>Yeah... IMO this is the language telling us "don't do that." &nbsp;for my part, I'm not really in the market for ideas about how to do this that cut against the grain of the language. &nbsp;I'd settle for a slightly less expressive API if it means avoiding surprising corner case behaviors. &nbsp;And there's so much more to discuss here than how to clean up this syntax. If someone comes up with an expressive notation that's free of issues, we can always implement it as an add-on later.</div><div><br></div><div>-Dave</div><div><br></div></body></html>