[swift-evolution] Strings in Swift 4

Gwendal Roué gwendal.roue at gmail.com
Mon Jan 23 22:34:17 CST 2017


> Le 24 janv. 2017 à 05:29, Gwendal Roué <gwendal.roue at gmail.com> a écrit :
> 
> 
>> Le 24 janv. 2017 à 04:31, Brent Royal-Gordon via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> a écrit :
>> 
>>>> 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.
>>> 
>>> Yeah, we thought about trying to build a DSL for that, but failed.  I think the best possible option would be something like:
>>> 
>>>  foo.comparison(case: .insensitive, locale: .current) < bar
>>> 
>>> The biggest problem is that you can build things like
>>> 
>>>    fu = foo.comparison(case: .insensitive, locale: .current)
>>>    br = bar.comparison(case: .sensitive)
>>>    fu < br // what does this mean?
>>> 
>>> We could even prevent such nonsense from compiling, but the cost in library API surface area is quite large.
>> 
>> Is it? I think we're talking, for each category of operation that can be localized like this:
>> 
>> * One type to carry an operand and its options.
>> * One method to construct this type.
>> * 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.)
>> 
>> 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. 
> 
> SQL has the `collate` keyword:
> 
> 	-- sort users by email, case insensitive
> 	select * from users order by email collate nocase
> 	-- look for a specific email, in a case insensitive way
> 	select * from users where email = 'foo at example.com <mailto:foo at example.com>' collate nocase
> 
> It is used as a decorator that modifies an existing sql snippet (a sort descriptor first, and a comparison last)
> 
> 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:
> 
> 	// sort users by email, case insensitive
> 	User.order(nameColumn.collating(.nocase))
> 	// look for a specific email, in a case insensitive way
> 	User.filter(nameColumn.collating(.nocase) == "foo at example.com <mailto:foo at example.com>")
> 
> Yes, it comes with extra operators so that nonsensical comparison are avoided.
> 
> But it just works.

I should have explained more the sql approach:

The collation (a comparison function) is attached to a *value*. It is part of its type. You can attach a collation to a table column, or, when a column has no collation, add the collation at the "call site", as in the examples above.

The collation belongs to the type, and the value "knows" how it is supposed to be compared.

An example of string which fits well in such a frame is hexadecimal representations of UUIDs: they should inherently be compared in a case-insensitive way.

That's why attaching the comparison options to the value is not necessarily a bad idea, and has been used for years, with success, by SQL.

Gwendal

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170124/296751fc/attachment.html>


More information about the swift-evolution mailing list