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

Merge ordered and unordered comparators #5845

Merged
merged 16 commits into from
Mar 11, 2023

Conversation

Akirathan
Copy link
Member

@Akirathan Akirathan commented Mar 7, 2023

Pull Request Description

Merge ordered and unordered comparators into a single one.

Important Notes

Comparator is now required to have only compare method:

type Comparator
  comapre : T -> T -> (Ordering|Nothing)
  hash : T -> Integer

Checklist

Please include the following checklist in your PR:

  • The documentation has been updated if necessary.
  • All code conforms to the
    Scala,
    Java,
    and
    Rust
    style guides.
  • All code has been tested:
    • Unit tests have been written where possible.
    • If GUI codebase was changed: Enso GUI was tested when built using BOTH
      ./run ide build and ./run ide watch.

@Akirathan Akirathan linked an issue Mar 7, 2023 that may be closed by this pull request
@Akirathan Akirathan force-pushed the wip/akirathan/merge-comparators-5818 branch from aae0541 to cae98e6 Compare March 7, 2023 18:09
@Akirathan Akirathan marked this pull request as ready for review March 8, 2023 12:09
@Akirathan
Copy link
Member Author

Benchmarks improved - sieve.enso 3x faster and EqualsBenchmarks are roughly 2x faster

@Akirathan Akirathan self-assigned this Mar 8, 2023
That rapidly decreased performance - #5709 (comment)
# Conflicts:
#	CHANGELOG.md
#	distribution/lib/Standard/Base/0.0.0-dev/src/Data/Json.enso
#	test/Table_Tests/src/Common_Table_Operations/Join/Join_Spec.enso
#	test/Tests/src/Data/Ordering_Spec.enso
#	test/Tests/src/Data/Text_Spec.enso
#	test/Tests/src/Data/Time/Duration_Spec.enso
Comment on lines 117 to 123
case Meta.is_same_object eq_self Default_Comparator of
True ->
case eq_self.is_ordered of
True ->
res = eq_self.compare self that
case res of
Ordering.Equal -> True
_ -> False
False ->
res = eq_self.equals self that
case res of
Nothing -> False
_ -> res
# Comparable.equals_builtin can return Nothing when self and that
# are incomparable.
case Comparable.equals_builtin self that of
True -> True
_ -> False
Copy link
Member

Choose a reason for hiding this comment

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

minor nitpick but I'm a bit surprised we do the case-of check instead of just delegating to Default_Comparator.compare which could be the place that will then call Comparable.equals_builtin self that?

Copy link
Member Author

Choose a reason for hiding this comment

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

Default_Comparator.compare x y has to handle three cases - x==y, x<y or x>y - which is implemented with three nested case expressions. If x and y are neither, i.e., are not equal, all of these three cases have to be evaluated. So this is, once again, because of the performance - it is just a shortcut.

Copy link
Member

Choose a reason for hiding this comment

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

OK.

I'm really surprised we have these 3 builtins. IMO one builtin compare x y returning -1, 0, +1 or null could work just as well or maybe even better.

Like, if you are comparing two Text values that have 1M characters of length (an exaggerated example but well...), assume the difference is at second to last character. The equals check will have to iterate the whole string and find the diff at the end, to determine they are not equal. But are they greater or smaller? Now we have to iterate the whole string once again...

Instead with compare approach we'd do this at one time.
I think even for integers/floats the JVM should be able to boil down a == + < into a single three-way compare instruction (although [citation needed]).

Copy link
Member Author

Choose a reason for hiding this comment

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

We don't have 3 builtins for comparisons, we have only 2 - EqualsNode (Comparable.equals_builtin) and LessThanNode (Comparable.less_than_builtin). Merging their functionality into one is inappropriate because many types that can be compared with ==, cannot be compared with < - Just compare the number of specializations we have in EqualsNode and compare it to the number of specializations in LessThanNode. Moreover, LessThanNode now has a different return value, as it can return Nothing for values that are incomparable.

The example with a string with 1M characters is, indeed, exaggerated. Besides, merging EqualsNode and LessThanNode in one single node might bring us some performance improvement. But comparing it to other low hanging fruits, like problems with nested case expressions, it would be negligible.

Copy link
Member

@radeusgd radeusgd left a comment

Choose a reason for hiding this comment

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

Looks good.

I will appreciate updating the docs along the lines of what was suggested. Especially the incomparable/partial-ordering concept is a bit subtle, let's try to explain it carefully. Remembering that we used to have ordered/unordered comparators where all elements behaved in one way or another. Now we have partial-orderings by default so we can have mixed behaviour, depending on what pair of values of a given type is compared.

@Akirathan Akirathan force-pushed the wip/akirathan/merge-comparators-5818 branch from d0c8778 to 635f1c9 Compare March 10, 2023 15:31
@Akirathan Akirathan added the CI: Ready to merge This PR is eligible for automatic merge label Mar 10, 2023
@mergify mergify bot merged commit 5f7a4a5 into develop Mar 11, 2023
@mergify mergify bot deleted the wip/akirathan/merge-comparators-5818 branch March 11, 2023 05:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CI: Ready to merge This PR is eligible for automatic merge
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Merge ordered and unordered comparators
4 participants