[Accepted] SE-0121: Remove Optional Comparison Operators


(Chris Lattner) #1

Proposal Link: https://github.com/apple/swift-evolution/blob/master/proposals/0121-remove-optional-comparison-operators.md

The review of "SE-0121: Remove Optional Comparison Operators" ran from Active review July 12...19. The proposal has been *accepted*.

Feedback has been universally positive from both the community and the core team, because it eliminates a surprising part of the Swift model at very little utility cost.

Thank you to Jacob Bandes-Storch for driving this discussion forward.

-Chris Lattner
Review Manager


(Jacob Bandes-Storch) #2

Great!

I have an attempted implementation here. Would appreciate if someone can
kick off a CI build/test.

https://github.com/apple/swift/pull/3637

···

On Wed, Jul 20, 2016 at 5:38 PM Chris Lattner via swift-evolution < swift-evolution@swift.org> wrote:

Proposal Link:
https://github.com/apple/swift-evolution/blob/master/proposals/0121-remove-optional-comparison-operators.md

The review of "SE-0121: Remove Optional Comparison Operators" ran from
Active review July 12...19. The proposal has been *accepted*.

Feedback has been universally positive from both the community and the
core team, because it eliminates a surprising part of the Swift model at
very little utility cost.

Thank you to Jacob Bandes-Storch for driving this discussion forward.

-Chris Lattner
Review Manager

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Lily Ballard) #3

Goddammit. I completely missed this thread, because Pipermail regularly decides not to deliver the swift-evolution-announce version of review threads (which means they bypass my inbox). Why does it do this? Most of the emails get delivered, but it just skips some of them, and I keep ending up missing review threads because of it.

This change is going to have a HUGE impact for me. I use this sort of comparison _all the time_ and find it incredibly useful, and have had literally zero bugs caused by this. Surely I can't be the only one who uses this. I am not looking forward to copying & pasting a reimplementation of the comparison functions into every single project I work on.

I'm also really concerned about how fast such a hugely-impactful change was proposed, accepted, and implemented. The proposal PR was submitted on July 12, merged the same day, and a review kicked off again on the same day. And the first thread the proposal referenced only happened the previous day, on July 11. And the implementation landed only 12 days later on July 24th. This was extremely fast and didn't even have time to have the proposal listed on apple/swift-evolution for people to find before the review kicked off. It looks like this was done so the change could be made before the end of source-breaking changes, but the fast-tracking of something like this means that people like me completely missed it, and now we're stuck with a highly-impactful change that we don't want. Fast-tracking proposals is understandable when they're largely additive, or they fix something that is widely accepted as a problem. But being able to compare optionals is not universally recognized as a problem, and I know for a fact I've weighed in on this subject in the past on swift-evolution. I do not think it was appropriate to fast-track this proposal.

-Kevin Ballard

···

On Wed, Jul 20, 2016, at 05:38 PM, Chris Lattner via swift-evolution wrote:

Proposal Link: https://github.com/apple/swift-evolution/blob/master/proposals/0121-remove-optional-comparison-operators.md

The review of "SE-0121: Remove Optional Comparison Operators" ran from Active review July 12...19. The proposal has been *accepted*.

Feedback has been universally positive from both the community and the core team, because it eliminates a surprising part of the Swift model at very little utility cost.

Thank you to Jacob Bandes-Storch for driving this discussion forward.

-Chris Lattner
Review Manager

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Tim Vermeulen) #4

What do you find so useful about them? And in what context does it make sense to you that `nil < .some(x)` always evaluates to true? When I found that out, I was very surprised by that behaviour (just like many others). Do you have examples of then an optional comparison makes the code clearer?

···

Goddammit. I completely missed this thread, because Pipermail regularly decides not to deliver the swift-evolution-announce version of review threads (which means they bypass my inbox). Why does it do this? Most of the emails get delivered, but it just skips some of them, and I keep ending up missing review threads because of it.

This change is going to have a HUGE impact for me. I use this sort of comparison _all the time_ and find it incredibly useful, and have had literally zero bugs caused by this. Surely I can't be the only one who uses this. I am not looking forward to copying&pasting a reimplementation of the comparison functions into every single project I work on.

I'm also really concerned about how fast such a hugely-impactful change was proposed, accepted, and implemented. The proposal PR was submitted on July 12, merged the same day, and a review kicked off again on the same day. And the first thread the proposal referenced only happened the previous day, on July 11. And the implementation landed only 12 days later on July 24th. This was extremely fast and didn't even have time to have the proposal listed on apple/swift-evolution for people to find before the review kicked off. It looks like this was done so the change could be made before the end of source-breaking changes, but the fast-tracking of something like this means that people like me completely missed it, and now we're stuck with a highly-impactful change that we don't want. Fast-tracking proposals is understandable when they're largely additive, or they fix something that is widely accepted as a problem. But being able to compare optionals is not universally recognized as a problem, and I know for a fact I've weighed in on this subject in the past on swift-evolution. I do not think it was appropriate to fast-track this proposal.

-Kevin Ballard

On Wed, Jul 20, 2016, at 05:38 PM, Chris Lattner via swift-evolution wrote:
> Proposal Link: https://github.com/apple/swift-evolution/blob/master/proposals/0121-remove-optional-comparison-operators.md
>
> The review of "SE-0121: Remove Optional Comparison Operators" ran from Active review July 12...19. The proposal has been *accepted*.
>
> Feedback has been universally positive from both the community and the core team, because it eliminates a surprising part of the Swift model at very little utility cost.
>
> Thank you to Jacob Bandes-Storch for driving this discussion forward.
>
> -Chris Lattner
> Review Manager
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution


(Chris Lattner) #5

Hi Kevin,

This fits into a more general idea of introducing a better “ordering” concept defined in terms of three way comparison results (less/equal/greater). This would then become the primitive that sort would be built on, and would allow deriving the user friendly operators like < and <=.

There was a sketch of this posted to swift-evolution several weeks ago, but I don’t have a link offhand.

-Chris

···

On Aug 26, 2016, at 6:01 PM, Kevin Ballard <kevin@sb.org> wrote:

This change is going to have a HUGE impact for me. I use this sort of comparison _all the time_ and find it incredibly useful, and have had literally zero bugs caused by this. Surely I can't be the only one who uses this. I am not looking forward to copying & pasting a reimplementation of the comparison functions into every single project I work on.


(Haravikk) #6

Can you give some examples as to how this will have such a huge impact? Now that we have the ?? operator it seems that this is fairly easy to replace:

  value < 5 // where value is of type Int?

With:

  (value ?? 0) < 5

The latter is completely clear what the behaviour of nil is.

Also, you can still re-add the operators where you need them, ideally with as limited a type as possible so you can make sure that it's behaviour is well defined.

···

On 27 Aug 2016, at 02:01, Kevin Ballard via swift-evolution <swift-evolution@swift.org> wrote:

This change is going to have a HUGE impact for me. I use this sort of comparison _all the time_ and find it incredibly useful, and have had literally zero bugs caused by this. Surely I can't be the only one who uses this. I am not looking forward to copying & pasting a reimplementation of the comparison functions into every single project I work on.


(Dave Abrahams) #7

It's very easy to write your own versions of these operators, should you
choose to keep using them. From that standpoint, I don't see why the
impact has to be huge.

···

on Fri Aug 26 2016, Kevin Ballard <swift-evolution@swift.org> wrote:

Goddammit. I completely missed this thread, because Pipermail
regularly decides not to deliver the swift-evolution-announce version
of review threads (which means they bypass my inbox). Why does it do
this? Most of the emails get delivered, but it just skips some of
them, and I keep ending up missing review threads because of it.

This change is going to have a HUGE impact for me. I use this sort of
comparison _all the time_ and find it incredibly useful, and have had
literally zero bugs caused by this. Surely I can't be the only one who
uses this. I am not looking forward to copying & pasting a
reimplementation of the comparison functions into every single project
I work on.

--
-Dave


(Xiaodi Wu) #8

Here's the link:
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160718/025132.html

···

On Sat, Aug 27, 2016 at 11:21 AM, Chris Lattner via swift-evolution < swift-evolution@swift.org> wrote:

On Aug 26, 2016, at 6:01 PM, Kevin Ballard <kevin@sb.org> wrote:
> This change is going to have a HUGE impact for me. I use this sort of
comparison _all the time_ and find it incredibly useful, and have had
literally zero bugs caused by this. Surely I can't be the only one who uses
this. I am not looking forward to copying & pasting a reimplementation of
the comparison functions into every single project I work on.

Hi Kevin,

This fits into a more general idea of introducing a better “ordering”
concept defined in terms of three way comparison results
(less/equal/greater). This would then become the primitive that sort would
be built on, and would allow deriving the user friendly operators like <
and <=.

There was a sketch of this posted to swift-evolution several weeks ago,
but I don’t have a link offhand.

-Chris

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Charlie Monroe) #9

I have personally (ab)used this for the following:

class User {
  var email: String
  var firstName: String?
  var lastName: String?
}

You have a list of users based on email, so last name is optional. In Swift 2.x, you can do:

users.sort({ $0.lastName < $1.lastName })

Now, you need to do:

users.sorted({
  guard let firstName = $0.0.lastName else {
    return true
  }
  
  guard let secondName = $0.1.lastName else {
    return false
  }
  
  return firstName < secondName
})

Which aside from being a brain teaser how to properly maintain ordering when $0.0's lastName != nil && $0.1's lastName == nil, adds additional few lines.

But I agree that it may come as confusing with Ints, etc. - with strings it kind of makes sense since nil is like an empty string which is placed in front of everything.

···

On Aug 27, 2016, at 1:46 PM, Haravikk via swift-evolution <swift-evolution@swift.org> wrote:

On 27 Aug 2016, at 02:01, Kevin Ballard via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

This change is going to have a HUGE impact for me. I use this sort of comparison _all the time_ and find it incredibly useful, and have had literally zero bugs caused by this. Surely I can't be the only one who uses this. I am not looking forward to copying & pasting a reimplementation of the comparison functions into every single project I work on.

Can you give some examples as to how this will have such a huge impact? Now that we have the ?? operator it seems that this is fairly easy to replace:

  value < 5 // where value is of type Int?

With:

  (value ?? 0) < 5

The latter is completely clear what the behaviour of nil is.

Also, you can still re-add the operators where you need them, ideally with as limited a type as possible so you can make sure that it's behaviour is well defined.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Lily Ballard) #10

I find it useful because Optionals show up all over the place, and it’s very convenient to be able to compare Optional values in a straightforward fashion. Especially when you have two Optional values to compare (as opposed to comparing an Optional with a non-Optional). `nil < .some(x)` evaluating to true makes sense because it’s the logical way to define that operator if you’re trying to make Optionals comparable (and if we had conditional protocol conformances then I’d say Optional should in fact be Comparable), as the absence of a value would quite reasonably be considered to be less than the presence of a value, assuming that there is an ordered relationship at all. And there’s already precedent for “empty” values sorting less than all other values (namely, the empty string sorts less than all other strings).

As for optional comparisons making the code cleaner, I end up using them all over the place. The case that motivated my email looked something along the lines of

  if request?.httpVersion < HTTPVersion(1.0) {
    // no keepalive
    disconnect()
  }

This particular case could be trivially replaced with

  if request.map({ $0.httpVersion < HTTPVersion(1.0) }) ?? true {

but it’s uglier and harder to read.

It’s easy to come up with contrived examples of comparing two optionals as well. A simplistic example is just sorting an array of optionals, or sorting an array of structs that contain an optional value.

-Kevin Ballard

···

On Aug 26, 2016, at 7:36 PM, Tim Vermeulen <tvermeulen@me.com> wrote:

What do you find so useful about them? And in what context does it make sense to you that `nil < .some(x)` always evaluates to true? When I found that out, I was very surprised by that behaviour (just like many others). Do you have examples of then an optional comparison makes the code clearer?

Goddammit. I completely missed this thread, because Pipermail regularly decides not to deliver the swift-evolution-announce version of review threads (which means they bypass my inbox). Why does it do this? Most of the emails get delivered, but it just skips some of them, and I keep ending up missing review threads because of it.

This change is going to have a HUGE impact for me. I use this sort of comparison _all the time_ and find it incredibly useful, and have had literally zero bugs caused by this. Surely I can't be the only one who uses this. I am not looking forward to copying&pasting a reimplementation of the comparison functions into every single project I work on.

I'm also really concerned about how fast such a hugely-impactful change was proposed, accepted, and implemented. The proposal PR was submitted on July 12, merged the same day, and a review kicked off again on the same day. And the first thread the proposal referenced only happened the previous day, on July 11. And the implementation landed only 12 days later on July 24th. This was extremely fast and didn't even have time to have the proposal listed on apple/swift-evolution for people to find before the review kicked off. It looks like this was done so the change could be made before the end of source-breaking changes, but the fast-tracking of something like this means that people like me completely missed it, and now we're stuck with a highly-impactful change that we don't want. Fast-tracking proposals is understandable when they're largely additive, or they fix something that is widely accepted as a problem. But being able to compare optionals is not universally recognized as a problem, and I know for a fact I've weighed in on this subject in the past on swift-evolution. I do not think it was appropriate to fast-track this proposal.

-Kevin Ballard

On Wed, Jul 20, 2016, at 05:38 PM, Chris Lattner via swift-evolution wrote:

Proposal Link: https://github.com/apple/swift-evolution/blob/master/proposals/0121-remove-optional-comparison-operators.md

The review of "SE-0121: Remove Optional Comparison Operators" ran from Active review July 12...19. The proposal has been *accepted*.

Feedback has been universally positive from both the community and the core team, because it eliminates a surprising part of the Swift model at very little utility cost.

Thank you to Jacob Bandes-Storch for driving this discussion forward.

-Chris Lattner
Review Manager

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Lily Ballard) #11

You could make the same argument for a lot of stuff the stdlib provides. For example, let's remove Optional.map since it's trivial to reimplement.

The problem is, if I have to reimplement this thing in every single project I touch, that's a huge impact. I shouldn't have to copy & paste a bunch of code into every single project. I'm already doing this with my replace(_:with:) function that you guys (Swift core team; I forget exactly who) didn't like, but that's at least simpler than the Optional comparison operators, and is only one function (and it's easier to work around the lack of this function if I don't want to reimplement it for a particular use).

-Kevin

···

On Sun, Aug 28, 2016, at 01:28 PM, Dave Abrahams via swift-evolution wrote:

on Fri Aug 26 2016, Kevin Ballard <swift-evolution@swift.org> wrote:

> Goddammit. I completely missed this thread, because Pipermail
> regularly decides not to deliver the swift-evolution-announce version
> of review threads (which means they bypass my inbox). Why does it do
> this? Most of the emails get delivered, but it just skips some of
> them, and I keep ending up missing review threads because of it.
>
> This change is going to have a HUGE impact for me. I use this sort of
> comparison _all the time_ and find it incredibly useful, and have had
> literally zero bugs caused by this. Surely I can't be the only one who
> uses this. I am not looking forward to copying & pasting a
> reimplementation of the comparison functions into every single project
> I work on.

It's very easy to write your own versions of these operators, should you
choose to keep using them. From that standpoint, I don't see why the
impact has to be huge.


(Javier Soto) #12

My biggest issue with Optional conforming to Comparable is that while a
default implementation may sometimes be useful, it may not necessarily be
the one you want. In that last example with lastName, if you wanted to
change the policy for whether users without last name appear first or last,
you'd have to write more verbose code anyway. Generally, reading that code
with just "<" I would never remember what Swift would do with nil (do they
go first or last?)

If you don't care that much, a simple one-liner without all those guards
could also be:

users.sorted { ($0.lastName ?? "") < ($1.lastName ?? "") }

···

On Sat, Aug 27, 2016 at 6:58 AM Charlie Monroe via swift-evolution < swift-evolution@swift.org> wrote:

I have personally (ab)used this for the following:

class User {
var email: String
var firstName: String?
var lastName: String?
}

You have a list of users based on email, so last name is optional. In
Swift 2.x, you can do:

users.sort({ $0.lastName < $1.lastName })

Now, you need to do:

users.sorted({
guard let firstName = $0.0.lastName else {
return true
}

guard let secondName = $0.1.lastName else {
return false
}

return firstName < secondName
})

Which aside from being a brain teaser how to properly maintain ordering
when $0.0's lastName != nil && $0.1's lastName == nil, adds additional few
lines.

But I agree that it may come as confusing with Ints, etc. - with strings
it kind of makes sense since nil is like an empty string which is placed in
front of everything.

On Aug 27, 2016, at 1:46 PM, Haravikk via swift-evolution < > swift-evolution@swift.org> wrote:

On 27 Aug 2016, at 02:01, Kevin Ballard via swift-evolution < > swift-evolution@swift.org> wrote:

This change is going to have a HUGE impact for me. I use this sort of
comparison _all the time_ and find it incredibly useful, and have had
literally zero bugs caused by this. Surely I can't be the only one who uses
this. I am not looking forward to copying & pasting a reimplementation of
the comparison functions into every single project I work on.

Can you give some examples as to how this will have such a huge impact?
Now that we have the ?? operator it seems that this is fairly easy to
replace:

value < 5 // where value is of type Int?

With:

(value ?? 0) < 5

The latter is completely clear what the behaviour of nil is.

Also, you can still re-add the operators where you need them, ideally with
as limited a type as possible so you can make sure that it's behaviour is
well defined.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

--
Javier Soto


(Magnus Ahltorp) #13

Without having tested it, something like this should work. In more complicated cases, make it a method on the struct.

users.sorted({ ($0.lastName ?? "") < ($1.lastName ?? "") })

/Magnus

···

27 Aug. 2016 15:58 Charlie Monroe via swift-evolution <swift-evolution@swift.org> wrote:
Now, you need to do:

users.sorted({
  guard let firstName = $0.0.lastName else {
    return true
  }
  
  guard let secondName = $0.1.lastName else {
    return false
  }
  
  return firstName < secondName
})


(David Hart) #14

I totally agree with Javier here. There is nothing obvious about nil being < or > than a non-nil value. As it's not obvious at all, having a default behaviour can be very surprising. i much prefer the explicitness that the proposal brought.

···

On 27 Aug 2016, at 16:07, Javier Soto via swift-evolution <swift-evolution@swift.org> wrote:

My biggest issue with Optional conforming to Comparable is that while a default implementation may sometimes be useful, it may not necessarily be the one you want. In that last example with lastName, if you wanted to change the policy for whether users without last name appear first or last, you'd have to write more verbose code anyway. Generally, reading that code with just "<" I would never remember what Swift would do with nil (do they go first or last?)

If you don't care that much, a simple one-liner without all those guards could also be:

users.sorted { ($0.lastName ?? "") < ($1.lastName ?? "") }

On Sat, Aug 27, 2016 at 6:58 AM Charlie Monroe via swift-evolution <swift-evolution@swift.org> wrote:
I have personally (ab)used this for the following:

class User {
  var email: String
  var firstName: String?
  var lastName: String?
}

You have a list of users based on email, so last name is optional. In Swift 2.x, you can do:

users.sort({ $0.lastName < $1.lastName })

Now, you need to do:

users.sorted({
  guard let firstName = $0.0.lastName else {
    return true
  }
  
  guard let secondName = $0.1.lastName else {
    return false
  }
  
  return firstName < secondName
})

Which aside from being a brain teaser how to properly maintain ordering when $0.0's lastName != nil && $0.1's lastName == nil, adds additional few lines.

But I agree that it may come as confusing with Ints, etc. - with strings it kind of makes sense since nil is like an empty string which is placed in front of everything.

On Aug 27, 2016, at 1:46 PM, Haravikk via swift-evolution <swift-evolution@swift.org> wrote:

On 27 Aug 2016, at 02:01, Kevin Ballard via swift-evolution <swift-evolution@swift.org> wrote:

This change is going to have a HUGE impact for me. I use this sort of comparison _all the time_ and find it incredibly useful, and have had literally zero bugs caused by this. Surely I can't be the only one who uses this. I am not looking forward to copying & pasting a reimplementation of the comparison functions into every single project I work on.

Can you give some examples as to how this will have such a huge impact? Now that we have the ?? operator it seems that this is fairly easy to replace:

  value < 5 // where value is of type Int?

With:

  (value ?? 0) < 5

The latter is completely clear what the behaviour of nil is.

Also, you can still re-add the operators where you need them, ideally with as limited a type as possible so you can make sure that it's behaviour is well defined.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

--
Javier Soto
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Lily Ballard) #15

My biggest issue with Optional conforming to Comparable is that while
a default implementation may sometimes be useful, it may not
necessarily be the one you want.

Isn't that true for almost everything? I could use the same argument to
say String shouldn't implement <, because it's not always the comparison
you want. For example, with the lastName example, you probably want case-
insensitive comparisons instead of case-sensitive comparisons, so you
probably shouldn't be using < at all.

In that last example with lastName, if you wanted to change the policy
for whether users without last name appear first or last, you'd have
to write more verbose code anyway. Generally, reading that code with
just "<" I would never remember what Swift would do with nil (do they
go first or last?)

Why would nil sort to the end? Empty values typically sort before
non-empty values, for example the empty string sorts before all
other strings.

-Kevin

···

On Sat, Aug 27, 2016, at 07:07 AM, Javier Soto via swift-evolution wrote:

If you don't care that much, a simple one-liner without all those
guards could also be:

users.sorted { ($0.lastName ?? "") < ($1.lastName ?? "") }
On Sat, Aug 27, 2016 at 6:58 AM Charlie Monroe via swift-evolution <swift- > evolution@swift.org> wrote:

I have personally (ab)used this for the following:

class User {
var email: String
var firstName: String?
var lastName: String?
}

You have a list of users based on email, so last name is optional. In
Swift 2.x, you can do:

users.sort({ $0.lastName < $1.lastName })

Now, you need to do:

users.sorted({
guard let firstName = $0.0.lastName else {
return true
}

guard let secondName = $0.1.lastName else {
return false
}

return firstName < secondName
})

Which aside from being a brain teaser how to properly maintain
ordering when $0.0's lastName != nil && $0.1's lastName == nil, adds
additional few lines.

But I agree that it may come as confusing with Ints, etc. - with
strings it kind of makes sense since nil is like an empty string
which is placed in front of everything.

On Aug 27, 2016, at 1:46 PM, Haravikk via swift-evolution <swift- >>> evolution@swift.org> wrote:

On 27 Aug 2016, at 02:01, Kevin Ballard via swift-evolution <swift- >>>> evolution@swift.org> wrote:

This change is going to have a HUGE impact for me. I use this sort
of comparison _all the time_ and find it incredibly useful, and
have had literally zero bugs caused by this. Surely I can't be the
only one who uses this. I am not looking forward to copying &
pasting a reimplementation of the comparison functions into every
single project I work on.

Can you give some examples as to how this will have such a huge
impact? Now that we have the ?? operator it seems that this is
fairly easy to replace:

value < 5 // where value is of type Int?

With:

(value ?? 0) < 5

The latter is completely clear what the behaviour of nil is.

Also, you can still re-add the operators where you need them,
ideally with as limited a type as possible so you can make sure that
it's behaviour is well defined.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

--
Javier Soto
_________________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Patrick Smith) #16

A little nicer I think is:

if request?.httpVersion.map({ $0 < HTTPVersion(1.0) }) ?? true {

It’s very explicit what the fallback is too, the original’s ambiguity makes me uncomfortable.

BTW, did you want to be checking for <= 1.0? With HTTP 1.0, it’s opt in. https://en.wikipedia.org/wiki/HTTP_persistent_connection

Patrick

···

On 28 Aug 2016, at 1:20 PM, Kevin Ballard via swift-evolution <swift-evolution@swift.org> wrote:

As for optional comparisons making the code cleaner, I end up using them all over the place. The case that motivated my email looked something along the lines of

if request?.httpVersion < HTTPVersion(1.0) {
   // no keepalive
   disconnect()
}

This particular case could be trivially replaced with

if request.map({ $0.httpVersion < HTTPVersion(1.0) }) ?? true {

but it’s uglier and harder to read.


(Goffredo Marocchi) #17

Goddammit. I completely missed this thread, because Pipermail
regularly decides not to deliver the swift-evolution-announce version
of review threads (which means they bypass my inbox). Why does it do
this? Most of the emails get delivered, but it just skips some of
them, and I keep ending up missing review threads because of it.

This change is going to have a HUGE impact for me. I use this sort of
comparison _all the time_ and find it incredibly useful, and have had
literally zero bugs caused by this. Surely I can't be the only one who
uses this. I am not looking forward to copying & pasting a
reimplementation of the comparison functions into every single project
I work on.

It's very easy to write your own versions of these operators, should you
choose to keep using them. From that standpoint, I don't see why the
impact has to be huge.

You could make the same argument for a lot of stuff the stdlib provides. For example, let's remove Optional.map since it's trivial to reimplement.

I think a case for removing it may be how much Optional.map is used to work around any pains regarding using optionals.

···

Sent from my iPhone

On 30 Aug 2016, at 05:00, Kevin Ballard via swift-evolution <swift-evolution@swift.org> wrote:

On Sun, Aug 28, 2016, at 01:28 PM, Dave Abrahams via swift-evolution wrote:

on Fri Aug 26 2016, Kevin Ballard <swift-evolution@swift.org> wrote:

The problem is, if I have to reimplement this thing in every single project I touch, that's a huge impact. I shouldn't have to copy & paste a bunch of code into every single project. I'm already doing this with my replace(_:with:) function that you guys (Swift core team; I forget exactly who) didn't like, but that's at least simpler than the Optional comparison operators, and is only one function (and it's easier to work around the lack of this function if I don't want to reimplement it for a particular use).

-Kevin
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(David Sweeris) #18

Does an empty Int sort before or after a non-empty Int?

···

Sent from my iPhone

On Aug 27, 2016, at 22:34, Kevin Ballard via swift-evolution <swift-evolution@swift.org> wrote:

On Sat, Aug 27, 2016, at 07:07 AM, Javier Soto via swift-evolution wrote:
My biggest issue with Optional conforming to Comparable is that while a default implementation may sometimes be useful, it may not necessarily be the one you want.

Isn't that true for almost everything? I could use the same argument to say String shouldn't implement <, because it's not always the comparison you want. For example, with the lastName example, you probably want case-insensitive comparisons instead of case-sensitive comparisons, so you probably shouldn't be using < at all.

In that last example with lastName, if you wanted to change the policy for whether users without last name appear first or last, you'd have to write more verbose code anyway. Generally, reading that code with just "<" I would never remember what Swift would do with nil (do they go first or last?)

Why would nil sort to the end? Empty values typically sort before non-empty values, for example the empty string sorts before all other strings.

-Kevin

If you don't care that much, a simple one-liner without all those guards could also be:

users.sorted { ($0.lastName ?? "") < ($1.lastName ?? "") }
On Sat, Aug 27, 2016 at 6:58 AM Charlie Monroe via swift-evolution <swift-evolution@swift.org> wrote:
I have personally (ab)used this for the following:

class User {
var email: String
var firstName: String?
var lastName: String?
}

You have a list of users based on email, so last name is optional. In Swift 2.x, you can do:

users.sort({ $0.lastName < $1.lastName })

Now, you need to do:

users.sorted({
guard let firstName = $0.0.lastName else {
return true
}

guard let secondName = $0.1.lastName else {
return false
}

return firstName < secondName
})

Which aside from being a brain teaser how to properly maintain ordering when $0.0's lastName != nil && $0.1's lastName == nil, adds additional few lines.

But I agree that it may come as confusing with Ints, etc. - with strings it kind of makes sense since nil is like an empty string which is placed in front of everything.

On Aug 27, 2016, at 1:46 PM, Haravikk via swift-evolution <swift-evolution@swift.org> wrote:

On 27 Aug 2016, at 02:01, Kevin Ballard via swift-evolution <swift-evolution@swift.org> wrote:

This change is going to have a HUGE impact for me. I use this sort of comparison _all the time_ and find it incredibly useful, and have had literally zero bugs caused by this. Surely I can't be the only one who uses this. I am not looking forward to copying & pasting a reimplementation of the comparison functions into every single project I work on.

Can you give some examples as to how this will have such a huge impact? Now that we have the ?? operator it seems that this is fairly easy to replace:

value < 5 // where value is of type Int?

With:

(value ?? 0) < 5

The latter is completely clear what the behaviour of nil is.

Also, you can still re-add the operators where you need them, ideally with as limited a type as possible so you can make sure that it's behaviour is well defined.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution
--
Javier Soto
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Tino) #19

My biggest issue with Optional conforming to Comparable is that while a default implementation may sometimes be useful, it may not necessarily be the one you want.

Isn't that true for almost everything?

That reminds me on a feature that has been discussed and added before:
Making tuples conform to Comparable (https://github.com/apple/swift-evolution/blob/master/proposals/0015-tuple-comparison-operators.md)
The implementation doesn't hurt me, but imho it's use is very limited as well.

As for comparing optionals, my preferred result would be an Optional<Bool>:
if (value < 5) ?? true {…
It makes no assumptions on the order, is clear and also concise.

Tino

There was a sketch of this posted to swift-evolution several weeks ago, but I don’t have a link offhand.

That, on the other hand, reminds me on the discussion about switching to another platform, because the mailing list sucks. I couldn't find a link to that one either (guess why :wink:

···

Am 28.08.2016 um 05:34 schrieb Kevin Ballard via swift-evolution <swift-evolution@swift.org>:


(Sean Heber) #20

I agree - I really don’t like these clever map constructs to work around optionals either and I avoid them at all costs. IMO they obscure intent pretty severely and shouldn’t be considered idiomatic Swift.

Depending on circumstances, I might do something along these lines:

guard let version = request?.httpVersion, version >= HTTPVersion(1.0) else {
  disconnect()
  return
}

That’s still more verbose, though, but it seems very explicit without relying on map cleverness.

l8r
Sean

···

On Aug 29, 2016, at 6:05 AM, Goffredo Marocchi via swift-evolution <swift-evolution@swift.org> wrote:

Whenever I see such examples I feel like map is being abused because of some of its properties rather than this. Ring the best way to deal with optionals.

Sent from my iPhone

On 29 Aug 2016, at 11:26, Patrick Smith via swift-evolution <swift-evolution@swift.org> wrote:

A little nicer I think is:

if request?.httpVersion.map({ $0 < HTTPVersion(1.0) }) ?? true {

It’s very explicit what the fallback is too, the original’s ambiguity makes me uncomfortable.

BTW, did you want to be checking for <= 1.0? With HTTP 1.0, it’s opt in. https://en.wikipedia.org/wiki/HTTP_persistent_connection

Patrick

On 28 Aug 2016, at 1:20 PM, Kevin Ballard via swift-evolution <swift-evolution@swift.org> wrote:

As for optional comparisons making the code cleaner, I end up using them all over the place. The case that motivated my email looked something along the lines of

if request?.httpVersion < HTTPVersion(1.0) {
  // no keepalive
  disconnect()
}

This particular case could be trivially replaced with

if request.map({ $0.httpVersion < HTTPVersion(1.0) }) ?? true {

but it’s uglier and harder to read.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution