I agree that there are refinements to operators that are needed, such as the ability to pick which ones to import and more flexibility in shadowing them, etc. But I think that&#39;s a whole nother discussion, and I rather think that string comparison is a distinctly poor use case for it. An operator is really tailored to do one unambiguous operation with two arguments. Here, there&#39;s more than one operation when it comes to string comparison and therefore multiple arguments. Why try to fit a square peg into a round hole? It&#39;s already possible to do what you suggest with ordinary function names, so what&#39;s different here seems to come down to new syntax that IMO should be designed separately in the context of operators, not really something to do with strings.<br><div class="gmail_quote"><div dir="ltr">On Tue, Jan 24, 2017 at 03:13 Jonathan Hull via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Breaking this into a different thread…<br class="gmail_msg">
<br class="gmail_msg">
One suggestion which I haven’t seen (maybe it is too crazy) is the idea of introducing shadowing of operators within a scope (similar to variables).<br class="gmail_msg">
<br class="gmail_msg">
Now this would need a TON of design work to make it actually work, but the gist would be:<br class="gmail_msg">
<br class="gmail_msg">
        if blah == foo {<br class="gmail_msg">
                //We can override/shadow the ‘&lt;‘ operator within this scope as long as the signature is the same<br class="gmail_msg">
                let (&lt;) = String.comparisonOperation(case: .insensitive, locale: .current) //Here we grab a closure produced by a static function on String<br class="gmail_msg">
<br class="gmail_msg">
                if a &lt; b {      //Within this scope &lt; will be case insensitive<br class="gmail_msg">
                        //Stuff<br class="gmail_msg">
                }<br class="gmail_msg">
        }<br class="gmail_msg">
        //Outside of the scope, &lt; is back to it’s lovable self<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
Thoughts on the general idea?<br class="gmail_msg">
<br class="gmail_msg">
Thanks,<br class="gmail_msg">
Jon<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
&gt; I know you want to defer this for now, so feel free to set this part of the email aside, but here&#39;s a quick list of solutions I&#39;ve ballparked:<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; 1. Your &quot;one operand carries the options&quot; solution.<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; 2. As I mentioned, do something that effectively overloads comparison operators to return them in a symbolic form. You&#39;re right about the ambiguity problem, though.<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; 3. Like #2, but with slightly modified operators, e.g.:<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt;       if localized(fu &amp;&lt; br, case: .insensitive) { … }<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; 4. Reintroduce something like the old `BooleanType` and have *all* comparisons construct a symbolic form that can be coerced to boolean. This is crazy, but actually probably useful in other places; I once experimented with constructing NSPredicates like this.<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt;       protocol BooleanProtocol { var boolValue: Bool { get } }<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt;       struct Comparison&lt;Operand: Comparable&gt; {<br class="gmail_msg">
&gt;               var negated: Bool<br class="gmail_msg">
&gt;               var sortOrder: SortOrder<br class="gmail_msg">
&gt;               var left: Operand<br class="gmail_msg">
&gt;               var right: Operand<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt;               func evaluate(_ actualSortOrder: SortOrder) -&gt; Bool {<br class="gmail_msg">
&gt;                       // There&#39;s circularity problems here, because `==` would itself return a `Comparison`,<br class="gmail_msg">
&gt;                       // but I think you get the idea.<br class="gmail_msg">
&gt;                       return (actualSortOrder == sortOrder) != negated<br class="gmail_msg">
&gt;               }<br class="gmail_msg">
&gt;       }<br class="gmail_msg">
&gt;       extension Comparison: BooleanProtocol {<br class="gmail_msg">
&gt;               var boolValue: Bool {<br class="gmail_msg">
&gt;                       return evaluate(left.compared(to: right))<br class="gmail_msg">
&gt;               }<br class="gmail_msg">
&gt;       }<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt;       func &lt; &lt;ComparableType: Comparable&gt;(lhs: ComparableType, rhs: ComparableType) -&gt; Comparison {<br class="gmail_msg">
&gt;               return Comparison(negated: false, sortOrder: .before, left: lhs, right: rhs)<br class="gmail_msg">
&gt;       }<br class="gmail_msg">
&gt;       func &lt;= &lt;ComparableType: Comparable&gt;(lhs: ComparableType, rhs: ComparableType) -&gt; Comparison {<br class="gmail_msg">
&gt;               return Comparison(negated: true, sortOrder: .after, left: lhs, right: rhs)<br class="gmail_msg">
&gt;       }<br class="gmail_msg">
&gt;       // etc.<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt;       // Now for our special String comparison thing:<br class="gmail_msg">
&gt;       func localized(_ expr: Comparison&lt;String&gt;, case: StringCaseSensitivity? = nil, …) -&gt; Bool {<br class="gmail_msg">
&gt;               return expr.evaluate(expr.left.compare(expr.right, case: case, …))<br class="gmail_msg">
&gt;       }<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; 5. Actually add some all-new piece of syntax that allows you to add options to an operator. Bad part is that this is ugly and kind of weird; good part is that this could probably be used in other places as well. Strawman example:<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt;       // Use:<br class="gmail_msg">
&gt;       if fu &lt; br %(case: .insensitive, locale: .current) { … }<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt;       // Definition:<br class="gmail_msg">
&gt;       func &lt; (lhs: String, rhs: String, case: StringCaseSensitivity? = nil, …) -&gt; Bool { … }<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; 6. Punt on this until we have macros. Once we do, have the function be a macro which alters the comparisons passed to it. Bad part is that this doesn&#39;t give us a solution for at least a version or two.<br class="gmail_msg">
_______________________________________________<br class="gmail_msg">
swift-evolution mailing list<br class="gmail_msg">
<a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a><br class="gmail_msg">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" class="gmail_msg" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="gmail_msg">
</blockquote></div>