diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array.enso index b92f572d49d4..684003f2d83b 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array.enso @@ -161,7 +161,7 @@ type Array Arguments: - order: The order in which the array elements are sorted. - on: A projection from the element type to the value of that element - being sorted on. If set to `Nothing` (the default argument), + being sorted on. If set to `Nothing` (the default), identity function will be used. - by: A function that compares the result of applying `on` to two elements, returning an an `Ordering` if the two elements are comparable @@ -183,6 +183,11 @@ type Array - *Average Time:* `O(n * log n)` - *Worst-Case Space:* `O(n)` additional + ? Incomparable values + Incomparable values are either values with different comparators or with + the same comparator returning `Nothing` from its `compare` method. + See the documentation of the `Ordering` module for more info. + ? Implementation Note The sort implementation is based upon an adaptive, iterative mergesort that requires far fewer than `n * log(n)` comparisons when the array @@ -198,8 +203,11 @@ type Array the comparators in the `self` array, with the exception of the group for the default comparator, which is always the first group. - Additionally, a warning will be attached, explaining that incomparable - values were encountered. + Additionally, an `Incomparable_Values` dataflow error will be returned + if the `on_incomparable` parameter is set to `Problem_Behavior.Report_Error`, + or a warning attached if the `on_incomparable` parameter is set to + `Problem_Behavior.Report_Warning` in case of encountering incomparable + values. It takes equal advantage of ascending and descending runs in the array, making it much simpler to merge two or more sorted arrays: simply @@ -216,8 +224,8 @@ type Array [Pair 1 2, Pair -1 8].to_array.sort Sort_Direction.Descending (_.first) > Example - Sorting an array with elements with different comparators. Values 1 - and My_Type have different comparators. 1 will be sorted before My_Type + Sorting an array with elements with different comparators. Values `1` + and `My_Type` have different comparators. `1` will be sorted before `My_Type` because it has the default comparator, and warning will be attached to the resulting array. diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Numbers.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Numbers.enso index 9c4fbb77224f..af99337638c8 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Numbers.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Numbers.enso @@ -280,6 +280,9 @@ type Number ## Checks equality of numbers, using an `epsilon` value. + ! Error Conditions + If either of the arguments is `Number.nan`, an `Incomparable_Values` error is raised. + Arguments: - that: The number to check equality against. - epsilon: The value by which `self` and `that` can be separated by before diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso index ba7917e37d64..6c714aa2419c 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso @@ -27,8 +27,8 @@ import project.Warning.Warning import project.IO -# We have to import also conversion methods, therefore, we import all from the Ordering -# module +## We have to import also conversion methods, therefore, we import all from the Ordering + module from project.Data.Ordering import all from project.Data.Boolean import Boolean, True, False from project.Data.Index_Sub_Range import Index_Sub_Range, take_helper, drop_helper @@ -848,7 +848,7 @@ type Vector a Arguments: - order: The order in which the vector elements are sorted. - on: A projection from the element type to the value of that element - being sorted on. If set to `Nothing` (the default argument), + being sorted on. If set to `Nothing` (the default), identity function will be used. - by: A function that compares the result of applying `on` to two elements, returning an an `Ordering` if the two elements are comparable @@ -870,6 +870,11 @@ type Vector a - *Average Time:* `O(n * log n)` - *Worst-Case Space:* `O(n)` additional + ? Incomparable values + Incomparable values are either values with different comparators or with + the same comparator returning `Nothing` from its `compare` method. + See the documentation of the `Ordering` module for more info. + ? Implementation Note The sort implementation is based upon an adaptive, iterative mergesort that requires far fewer than `n * log(n)` comparisons when the vector @@ -885,8 +890,11 @@ type Vector a the comparators in the `self` vector, with the exception of the group for the default comparator, which is always the first group. - Additionally, a warning will be attached, explaining that incomparable - values were encountered. + Additionally, an `Incomparable_Values` dataflow error will be returned + if the `on_incomparable` parameter is set to `Problem_Behavior.Report_Error`, + or a warning attached if the `on_incomparable` parameter is set to + `Problem_Behavior.Report_Warning` in case of encountering incomparable + values. It takes equal advantage of ascending and descending runs in the array, making it much simpler to merge two or more sorted arrays: simply @@ -903,8 +911,8 @@ type Vector a [Pair 1 2, Pair -1 8].sort Sort_Direction.Descending (_.first) > Example - Sorting a vector with elements with different comparators. Values 1 - and My_Type have different comparators. 1 will be sorted before My_Type + Sorting a vector with elements with different comparators. Values `1` + and `My_Type` have different comparators. `1` will be sorted before `My_Type` because it has the default comparator, and warning will be attached to the resulting vector. @@ -915,11 +923,7 @@ type Vector a True -> self.map it-> Comparable.from it False -> self.map it-> Comparable.from (on it) compare_funcs = comps.map (it-> it.compare) - problem_behavior = case on_incomparable of - Problem_Behavior.Ignore -> 0 - Problem_Behavior.Report_Warning -> 1 - Problem_Behavior.Report_Error -> 2 - self.sort_builtin order.to_sign comps compare_funcs by on problem_behavior + self.sort_builtin order.to_sign comps compare_funcs by on on_incomparable.to_number ## UNSTABLE Keeps only unique elements within the vector, removing any duplicates. diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Errors/Problem_Behavior.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Errors/Problem_Behavior.enso index 2b05336ffe73..969d8a78010b 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Errors/Problem_Behavior.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Errors/Problem_Behavior.enso @@ -164,3 +164,11 @@ type Problem_Behavior warnings = Warning.get_all result . map .value cleared_result = Warning.set result [] self.attach_problems_after cleared_result warnings + + ## PRIVATE + Returns a mapping of Problem_Behavior constructors to an integer. + Used for sending the number to Java, rather than sending the atom. + to_number self = case self of + Ignore -> 0 + Report_Warning -> 1 + Report_Error -> 2 diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/ordering/SortArrayNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/ordering/SortArrayNode.java index f4f9c9c02f5c..1ed278790603 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/ordering/SortArrayNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/ordering/SortArrayNode.java @@ -5,10 +5,7 @@ import org.enso.interpreter.dsl.BuiltinMethod; import org.enso.interpreter.runtime.state.State; -/** - * Just a wrapper for {@code Array.sort_builtin} that delegates to {@code Vector.sort_builtin}. This - * is a temporary workaround until Array and Vector are fully merged into a single type. - */ +/** Just a wrapper for {@code Array.sort_builtin} that delegates to {@code Vector.sort_builtin}. */ @BuiltinMethod(type = "Array", name = "sort_builtin") public final class SortArrayNode extends Node { @Child private SortVectorNode sortVectorNode = SortVectorNode.build(); diff --git a/test/Tests/src/Data/Ordering_Spec.enso b/test/Tests/src/Data/Ordering_Spec.enso index 8672d48b9060..098e44f34cc3 100644 --- a/test/Tests/src/Data/Ordering_Spec.enso +++ b/test/Tests/src/Data/Ordering_Spec.enso @@ -58,8 +58,8 @@ type No_Comp_Type expect_incomparable_warn : Any -> Any -> Any -> Nothing expect_incomparable_warn left_val right_val result = # Incomparable values warning wraps Text values in simple quotes - left_val_text = if Meta.is_a left_val Text then "'" + left_val + "'" else left_val.to_text - right_val_text = if Meta.is_a right_val Text then "'" + right_val + "'" else right_val.to_text + left_val_text = left_val.pretty + right_val_text = right_val.pretty expected_warn_msg_left = "Values " + left_val_text + " and " + right_val_text + " are incomparable" expected_warn_msg_right = "Values " + right_val_text + " and " + left_val_text + " are incomparable" has_expected_warning = Warning.get_all result . map (_.value) . any (it-> it == expected_warn_msg_left || it == expected_warn_msg_right) @@ -72,7 +72,7 @@ expect_no_warns result = # === The Tests === spec = - topo_sort_pending = "Waiting for implementation of topological sort (https://github.com/enso-org/enso/issues/5742)" + topo_sort_pending = "Waiting for implementation of topological sort (https://github.com/enso-org/enso/issues/5834)" Test.group "Default comparator" <| Test.specify "should support custom comparator" <| @@ -220,11 +220,11 @@ spec = [My_Type.Value 1, Ord.Value 1, 20, 10].sort . should_equal [10, 20, My_Type.Value 1, Ord.Value 1] [Ord.Value 1, 20, 10, My_Type.Value 1].sort . should_equal [10, 20, My_Type.Value 1, Ord.Value 1] - Test.specify "should be able to sort even unordered values" pending="https://github.com/enso-org/enso/issues/5834" <| + Test.specify "should be able to sort even unordered values" pending=topo_sort_pending <| [Ord.Value 2, UPair.Value "a" "b", Ord.Value 1, UPair.Value "c" "d"].sort . should_equal [Ord.Value 2, Ord.Value 1, UPair.Value "a" "b", UPair.Value "c" "d"] [Ord.Value 2, UPair.Value "X" "Y", Ord.Value 1, UPair.Value "c" "d"].sort . should_equal [Ord.Value 2, Ord.Value 1, UPair.Value "X" "Y", UPair.Value "c" "d"] - Test.specify "should produce warning when sorting unordered values" pending="https://github.com/enso-org/enso/issues/5834" <| + Test.specify "should produce warning when sorting unordered values" pending=topo_sort_pending <| expect_incomparable_warn (UPair.Value 1 2) (UPair.Value 3 4) [UPair.Value 1 2, UPair.Value 3 4].sort