[swift-evolution] String Comparison (was: Strings in Swift 4)

Xiaodi Wu xiaodi.wu at gmail.com
Tue Jan 24 06:23:59 CST 2017


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'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'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's already possible to do what you suggest with ordinary function
names, so what'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.
On Tue, Jan 24, 2017 at 03:13 Jonathan Hull via swift-evolution <
swift-evolution at swift.org> wrote:

> Breaking this into a different thread…
>
> 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).
>
> Now this would need a TON of design work to make it actually work, but the
> gist would be:
>
>         if blah == foo {
>                 //We can override/shadow the ‘<‘ operator within this
> scope as long as the signature is the same
>                 let (<) = String.comparisonOperation(case: .insensitive,
> locale: .current) //Here we grab a closure produced by a static function on
> String
>
>                 if a < b {      //Within this scope < will be case
> insensitive
>                         //Stuff
>                 }
>         }
>         //Outside of the scope, < is back to it’s lovable self
>
>
> Thoughts on the general idea?
>
> Thanks,
> Jon
>
>
> > I know you want to defer this for now, so feel free to set this part of
> the email aside, but here's a quick list of solutions I've ballparked:
> >
> > 1. Your "one operand carries the options" solution.
> >
> > 2. As I mentioned, do something that effectively overloads comparison
> operators to return them in a symbolic form. You're right about the
> ambiguity problem, though.
> >
> > 3. Like #2, but with slightly modified operators, e.g.:
> >
> >       if localized(fu &< br, case: .insensitive) { … }
> >
> > 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.
> >
> >       protocol BooleanProtocol { var boolValue: Bool { get } }
> >
> >       struct Comparison<Operand: Comparable> {
> >               var negated: Bool
> >               var sortOrder: SortOrder
> >               var left: Operand
> >               var right: Operand
> >
> >               func evaluate(_ actualSortOrder: SortOrder) -> Bool {
> >                       // There's circularity problems here, because `==`
> would itself return a `Comparison`,
> >                       // but I think you get the idea.
> >                       return (actualSortOrder == sortOrder) != negated
> >               }
> >       }
> >       extension Comparison: BooleanProtocol {
> >               var boolValue: Bool {
> >                       return evaluate(left.compared(to: right))
> >               }
> >       }
> >
> >       func < <ComparableType: Comparable>(lhs: ComparableType, rhs:
> ComparableType) -> Comparison {
> >               return Comparison(negated: false, sortOrder: .before,
> left: lhs, right: rhs)
> >       }
> >       func <= <ComparableType: Comparable>(lhs: ComparableType, rhs:
> ComparableType) -> Comparison {
> >               return Comparison(negated: true, sortOrder: .after, left:
> lhs, right: rhs)
> >       }
> >       // etc.
> >
> >       // Now for our special String comparison thing:
> >       func localized(_ expr: Comparison<String>, case:
> StringCaseSensitivity? = nil, …) -> Bool {
> >               return expr.evaluate(expr.left.compare(expr.right, case:
> case, …))
> >       }
> >
> > 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:
> >
> >       // Use:
> >       if fu < br %(case: .insensitive, locale: .current) { … }
> >
> >       // Definition:
> >       func < (lhs: String, rhs: String, case: StringCaseSensitivity? =
> nil, …) -> Bool { … }
> >
> > 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't give us a solution for at least a version or two.
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170124/bc95f7f0/attachment.html>


More information about the swift-evolution mailing list