Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't override neqv in Order #2230

Closed
wants to merge 1 commit into from

Conversation

ceedubs
Copy link
Contributor

@ceedubs ceedubs commented Apr 16, 2018

Eq provides a reasonable default implementation of neqv:

def neqv(x: A, y: A): Boolean = !eqv(x, y)

Before this change, Order overrides this default implementation as:

compare(x, y) != 0

I think that this override is questionable for a few reasons:

  • The negation of eqv seems like the most straightforward implementation of
    neqv to me
  • It seems like an oversight that Order overrides neqv but PartialOrder
    does not.
  • If someone is overriding eqv on an Order instance, presumably they are
    doing it because their eqv implelentation can be faster than doing a full
    compare. If this is the case and they don't override neqv, it would be
    better for them to inherit a !eqv implementation.

As a sidenote, the current implementation leads to a lack of symmetry
between === and =!= in the presence of null. "foo" === null
returns false while "foo" =!= null throws an NPE. I generally agree
with the decision in Cats to not perform special-handling of null.
However, the way that I ran into this was when adding a linting rule
that forbids non type-safe equality (== and !=), and it is kind of a
bummer that if you are working with a third-party library that might
return null and you want to safeguard against that you can't just
check for x =!= null instead of x != null to satisfy the linting
rule. You can do something like Option(x).isDefined, but that
introduces an extra allocation and seems a little roundabout to me.

Eq provides a reqsonable default implementation of `neqv`:

```scala
def neqv(x: A, y: A): Boolean = !eqv(x, y)
```

Before this change, `Order` overrides this default implementation as:

```scala
compare(x, y) != 0
```

I think that this override is questionable for a few reasons:

- The negation of `eqv` seems like the most straightforward implementation of
`neqv` to me
- It seems like an oversight that `Order` overrides `neqv` but `PartialOrder`
does not.
- If someone is overriding `eqv` on an `Order` instance, presumably they are
doing it because their `eqv` implelentation can be faster than doing a full
`compare`. If this is the case and they don't override `neqv`, it would be
better for them to inherit a !eqv` implementation.

As a sidenote, the current implementation leads to a lack of symmetry
between `===` and `=!=` in the presence of `null`. `"foo" === null`
returns `false` while `"foo" =!= null` throws an NPE. I generally agree
with the decision in Cats to not perform special-handling of `null`.
However, the way that I ran into this was when adding a linting rule
that forbids non type-safe equality (== and !=), and it is kind of a
bummer that if you are working with a third-party library that might
return `null` and you want to safeguard against that you can't just
check for `x =!= null` instead of `x != null` to satisfy the linting
rule. You can do something like `Option(x).isDefined`, but that
introduces an extra allocation and seems a little roundabout to me.
Copy link
Member

@LukaJCB LukaJCB left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@johnynek
Copy link
Contributor

👍

@ceedubs
Copy link
Contributor Author

ceedubs commented Apr 16, 2018

Oh this isn't binary compatible in Scala 2.10 and 2.11 :(

@ceedubs
Copy link
Contributor Author

ceedubs commented Apr 17, 2018

To get around the binary compatibility issue, I guess that I could keep the override but change the implementation to the same one as defined in Equal. Should I go ahead and do that?

ceedubs added a commit to ceedubs/cats that referenced this pull request Apr 17, 2018
@ceedubs
Copy link
Contributor Author

ceedubs commented Apr 17, 2018

Replaced by #2232

@ceedubs ceedubs closed this Apr 17, 2018
kailuowang pushed a commit that referenced this pull request Apr 17, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants