<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Now that I think more about it, tainting strings with a comparison behavior may be a bad idea:<div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>// not a so good idea, after all</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let foo = "foo".comparison(case: .insensitive, locale: .current)</div><div class=""><br class=""></div><div class="">Problems are:</div><div class=""><br class=""></div><div class="">- Two strings tainted with the same comparison behavior should be comparable, but two strings tainted with different behaviors should not. I'm not sure that the Swift type system allows that. In the current state of affairs, such restrictions are only available to *types*, which implies that comparisons should be types as well. But types can't be built at runtime from other types: there's not way for a runtime-chosen locale to be able to build a type.</div><div class=""><br class=""></div><div class="">- Tainting strings is an old, and unsolved problem. If you're allowed to taint for comparison, why can't you taint for confidence (user input), needing escaping (for HTML, shell, SQL, javscript, etc.), and a whole bunch of other dimensions I don't even think of? We're already discussing different types for strings and substrings... Do we really want a combinatorial explosion of types?</div><div class=""><br class=""></div><div class="">- Should we restrict support for comparison behaviors to strings only? `Sequence.lexicographicallyPrecedes(_:by:)` is interested in comparison behaviors as well, and it extends much further than just Strings.</div><div class=""><br class=""></div><div class="">So all in all, I think that isolating comparison behaviors from Strings may be a much better idea.</div><div class=""><br class=""></div><div class="">Gwendal</div><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">Le 24 janv. 2017 à 08:18, David Hart <<a href="mailto:david@hartbit.com" class="">david@hartbit.com</a>> a écrit :</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="">Seems like a good solution to me.</div><div class=""><br class="">On 24 Jan 2017, at 05:29, Gwendal Roué via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:<br class=""><br class=""></div><blockquote type="cite" class=""><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">Le 24 janv. 2017 à 04:31, Brent Royal-Gordon via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> a écrit :</div><br class="Apple-interchange-newline"><div class=""><div class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" 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 < 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. I think the best possible option would be something like:<br class=""><br class=""> foo.comparison(case: .insensitive, locale: .current) < bar<br class=""><br class="">The biggest problem is that you can build things like<br class=""><br class=""> fu = foo.comparison(case: .insensitive, locale: .current)<br class=""> br = bar.comparison(case: .sensitive)<br class=""> fu < 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=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Is it? I think we're talking, for each category of operation that can be localized like this:</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">* One type to carry an operand and its options.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">* One method to construct this type.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">* One alternate version of each operator which accepts an operand+options parameter. (I'm thinking it should always be the right-hand side, so the long stuff ends up at the end; Larry Wall noted this follows an "end-weight principle" in natural languages.)</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">I suspect that most solutions will at least require some sort of overload on the comparison operators, so this may be as parsimonious as we can get.<span class="Apple-converted-space"> </span></span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""></div></div></blockquote></div><br class=""><div class="">SQL has the `collate` keyword:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>-- sort users by email, case insensitive</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>select * from users order by email collate nocase</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>-- look for a specific email, in a case insensitive way</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>select * from users where email = '<a href="mailto:foo@example.com" class="">foo@example.com</a>' collate nocase</div><div class=""><br class=""></div><div class="">It is used as a decorator that modifies an existing sql snippet (a sort descriptor first, and a comparison last)</div><div class=""><br class=""></div><div class="">When designing an SQL building to Swift, I chose the `nameColumn.collating(.nocase)` approach, because it allowed a common Swift syntax for both use cases:</div><div class=""><br class=""></div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>// sort users by email, case insensitive</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>User.order(nameColumn.collating(.nocase))</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>// look for a specific email, in a case insensitive way</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>User.filter(nameColumn.collating(.nocase) == "<a href="mailto:foo@example.com" class="">foo@example.com</a>")</div><div class=""><br class=""></div></div><div class="">Yes, it comes with extra operators so that nonsensical comparison are avoided.</div><div class=""><br class=""></div><div class="">But it just works.</div><div class=""><br class=""></div><div class="">Gwendal</div><div class=""><br class=""></div></div></blockquote><blockquote type="cite" class=""><div class=""><span class="">_______________________________________________</span><br class=""><span class="">swift-evolution mailing list</span><br class=""><span class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a></span><br class=""><span class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br class=""></div></blockquote></div></div></blockquote></div><br class=""></div></body></html>