[swift-evolution] Strings in Swift 4

Dave Abrahams dabrahams at apple.com
Sun Jan 22 14:12:26 CST 2017



Sent from my iPad

> On Jan 22, 2017, at 11:25 AM, Karim Nassar <karim at karimnassar.com> wrote:
> 
>> From: Dave Abrahams <dabrahams at apple.com>
>> To: Brent Royal-Gordon <brent at architechies.com>
>> 
>>> 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:
>>> 
>>>   if foo.compared(to: bar, case: .insensitive, locale: .current) == .before { … }
>> 
>> Right.  We intend to keep the usual comparison operators.
>> 
>> Poor readability of "foo <=> bar == .before" is another reason we think that giving up on "<=>" is no great loss.
>> 
>>> 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.
>> 
>>> 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:
>>> 
>>>   if StringOptions(case: .insensitive, locale: .current).compare(foo < bar) { … }
>> 
>> Yeah, we can't do that without making 
>> 
>> 	let a = foo < bar
>> 
>> ambiguous
> 
> 
> So, cue crazy idea #1, but what about something like this?
> 
> struct StringComparison {
> 
> 	let leftHand: String
> 	let rightHand: String
> 	let comparison: SortOrder
> 
> 	var insensitive: Bool {
> 		...
> 	}
> 	// … etc
> }
> 
> func <(lhs: String, rhs: String) -> StringComparison { // similar for ==, >, etc.
> 	return StringComparison(leftHand: lhs, rightHand: rhs, comparison: .before)
> }
> 
> Then:
> 
> 	if (a < b).insensitive {
> 		...
> 	}
> 
> This would fix the ambiguity of:
> 
> 	let a = foo < bar // ‘a' is StringComparison
> 	if a.insensitive {
> 
> 	}
> 
> 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:
> 
> 	if a < b { // case-sensitive, non-localized compare
> 		...
> 	}
> 
> ...but I can’t figure out how to make that work without the old BooleanType protocol, maybe someone smarter than I could…

Yeah... IMO this is the language telling us "don't do that."  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.  I'd settle for a slightly less expressive API if it means avoiding surprising corner case behaviors.  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.

-Dave

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170122/95a10ad0/attachment.html>


More information about the swift-evolution mailing list