Skip to content

Commit

Permalink
Ordering.compare is the preferred way to compare two objects and get …
Browse files Browse the repository at this point in the history
…an Ordering
  • Loading branch information
JaroslavTulach committed Jul 9, 2024
1 parent f5f1b91 commit 091b0fd
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 41 deletions.
26 changes: 8 additions & 18 deletions distribution/lib/Standard/Base/0.0.0-dev/src/Data/Ordering.enso
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@ import project.Data.Numbers.Integer
import project.Data.Numbers.Number
import project.Error.Error
import project.Errors.Common.Incomparable_Values
import project.Errors.Common.Type_Error
import project.Errors.Illegal_State.Illegal_State
import project.Errors.Unimplemented.Unimplemented
import project.Meta
import project.Meta.Atom
import project.Nothing.Nothing
import project.Panic.Panic
from project.Data.Boolean import Boolean, False, True
from project.Internal.Ordering_Helpers import all

Expand Down Expand Up @@ -124,11 +122,11 @@ type Comparable
```
new value:Any comparator:Any -> Comparable = Comparable.By value comparator

compare self that:Comparable = case Meta.is_same_object self.comparator that.comparator of
True -> self.comparator.compare self.value that.value
False -> Error.throw (Incomparable_Values.Error self that)
compare self that -> Ordering ! Incomparable_Values =
Ordering.compare self that

hash self -> Integer = self.comparator.hash self.value
hash self -> Integer =
self.comparator.hash self.value

## PRIVATE
Default implementation of a _comparator_.
Expand Down Expand Up @@ -158,7 +156,8 @@ type Default_Comparator
comparator. It is assumed that the given atom has a custom comparator, that is
a comparator different than `Default_Comparator`.
hash_callback : Atom -> Integer
hash_callback atom = (Comparable.from atom).hash atom
hash_callback atom =
Comparable.from atom . hash

## PRIVATE
A callback allowing to compare two atoms with a custom comparator.
Expand All @@ -182,17 +181,8 @@ type Ordering
## A representation that the first value orders as greater than the second.
Greater

## PRIVATE
ADVANCED
Compares values and returns an Ordering.
compare : Any -> Any -> Ordering ! Incomparable_Values
compare x y =
safe_predicate ~action -> Boolean = Panic.catch Type_Error action=action (_-> False)

if safe_predicate x<y then Ordering.Less else
if safe_predicate x==y then Ordering.Equal else
if safe_predicate x>y then Ordering.Greater else
Error.throw (Incomparable_Values.Error x y)
## Compares values and returns an Ordering.
compare x y -> Ordering ! Incomparable_Values = compare_with_comparators x y

## GROUP Conversions
ICON convert
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ private
import project.Any.Any
from project.Data.Boolean import Boolean, False, True
from project.Data.Ordering import all
import project.Errors.Common.Type_Error
import project.Errors.Common.Incomparable_Values
import project.Error.Error
import project.Panic.Panic
import project.Meta
from project.Function import identity

## PRIVATE
Checks if the comparators for the given objects are both of the same type. If so,
Expand All @@ -18,6 +21,18 @@ assert_same_comparators this that ~action =
True -> action comp_this.comparator
False -> Error.throw (Incomparable_Values.Error this that)

compare_with_comparators this that -> Ordering ! Incomparable_Values =
any_result = Panic.catch Type_Error handler=identity <|
comp_this = Comparable.from this
comp_that = Comparable.from that

if Meta.is_same_object comp_this.comparator comp_that.comparator then
comp_this.comparator.compare comp_this.value comp_that.value

case any_result of
result:Ordering -> result
_ -> Error.throw (Incomparable_Values.Error this that)

## PRIVATE
type Positive_Integer_Comparator
## PRIVATE
Expand All @@ -30,7 +45,7 @@ type Positive_Integer_Comparator
## PRIVATE
type Ordering_Comparator
## PRIVATE
compare x y = (Comparable.from x.to_sign).compare y.to_sign
compare x:Ordering y:Ordering = Ordering.compare x.to_sign y.to_sign

## PRIVATE
hash x = x.to_sign
hash x:Ordering = x.to_sign
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type Bits
type Bits_Comparator
## PRIVATE
compare : Bits -> Bits -> Ordering
compare x y = Comparable.from x.to_integer . compare x.to_integer y.to_integer
compare x y = Ordering.compare x.to_integer y.to_integer

## PRIVATE
hash : Bits -> Integer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,25 +99,26 @@ boolean equalsAtomsWithCustomComparator(
var ctx = EnsoContext.get(this);
var args = new Object[] {cachedComparator, self, other};
var result = invokeNode.execute(compareFn, null, State.create(ctx), args);
assert orderingOrNull(this, ctx, result, compareFn);
assert orderingOrNullOrError(this, ctx, result, compareFn);
return ctx.getBuiltins().ordering().newEqual() == result;
}

@TruffleBoundary
private static boolean orderingOrNull(Node where, EnsoContext ctx, Object obj, Function fn) {
private static boolean orderingOrNullOrError(
Node where, EnsoContext ctx, Object obj, Function fn) {
var type = TypeOfNode.getUncached().execute(obj);
if (type == ctx.getBuiltins().ordering().getType() || type == ctx.getBuiltins().nothing()) {
if (type == ctx.getBuiltins().ordering().getType()) {
return true;
}
if (type == ctx.getBuiltins().nothing()) {
return true;
}
if (type == ctx.getBuiltins().dataflowError()) {
return true;
} else {
var msg =
"Expecting Ordering or Nothing, but got: "
+ obj
+ " with type "
+ type
+ " calling "
+ fn;
throw ctx.raiseAssertionPanic(where, msg, null);
}
var msg =
"Expecting Ordering or Nothing, but got: " + obj + " with type " + type + " calling " + fn;
throw ctx.raiseAssertionPanic(where, msg, null);
}

@Specialization(
Expand Down
4 changes: 1 addition & 3 deletions test/Base_Tests/src/Data/Ordering/Comparator_Spec.enso
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ type Ord
# The comparison is reverted, i.e., `x < y` gives result for `y.number < x.number`.
type Ord_Comparator
compare x:Ord y:Ord =
cx = Comparable.from x.number
cy = Comparable.from y.number
cx.compare cy
Ordering.compare x.number y.number
hash x = (Comparable.from x.number) . hash

Comparable.from (that:Ord) = Comparable.new that Ord_Comparator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@ type My_Type

type My_Type_Comparator
compare my_1 my_2 =
comp = Comparable.from my_1.x
comp.compare (my_1.x + my_1.y) (my_2.x + my_2.y)
Ordering.compare (my_1.x + my_1.y) (my_2.x + my_2.y)

hash my_type = Comparable.from my_type.x . hash (my_type.x + my_type.y)
hash my_type = Comparable.from (my_type.x + my_type.y) . hash

Comparable.from (that:My_Type) = Comparable.new that My_Type_Comparator

Expand Down
4 changes: 2 additions & 2 deletions test/Table_Tests/src/In_Memory/Table_Spec.enso
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ type My_Comparator
compare left right =
left_sum = left.x + left.y
right_sum = right.x + right.y
(Comparable.from left_sum) . compare left_sum right_sum
Ordering.compare left_sum right_sum

hash my =
sum = my.x + my.y
Comparable.from sum . hash sum
Comparable.from sum . hash

Comparable.from (that:My) = Comparable.new that My_Comparator

Expand Down

0 comments on commit 091b0fd

Please sign in to comment.