diff --git a/CHANGELOG.md b/CHANGELOG.md index 9322044aa1e9..1fdb6944c550 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ - [Implemented `Vector.flatten`][3259] - [Significant performance improvement in `Natural_Order` and new `Faker` methods added to `Standard.Test`][3276] +- [Implemented `Integer.parse`][3283] [debug-shortcuts]: https://github.com/enso-org/enso/blob/develop/app/gui/docs/product/shortcuts.md#debug @@ -68,6 +69,7 @@ [3259]: https://github.com/enso-org/enso/pull/3259 [3273]: https://github.com/enso-org/enso/pull/3273 [3276]: https://github.com/enso-org/enso/pull/3276 +[3283]: https://github.com/enso-org/enso/pull/3283 #### Enso Compiler diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Number/Extensions.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Number/Extensions.enso index e51739f1d19d..ff8b6dac38e3 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Number/Extensions.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Number/Extensions.enso @@ -1,5 +1,6 @@ from Standard.Base import all hiding Parse_Error +polyglot java import java.lang.Long polyglot java import java.lang.Double polyglot java import java.lang.Math polyglot java import java.lang.String @@ -252,6 +253,24 @@ Number.max that = if this > that then this else that Number.to_json : Json.Number Number.to_json = Json.Number this +## ALIAS From Text + + Parses a textual representation of an integer into an integer number, returning + a `Parse_Error` if the text does not represent a valid integer. + + Arguments: + - text: The text to parse into a integer. + - radix: The number base to use for parsing (defaults to 10). + + > Example + Parse the text "20220216" into an integer number. + + Integer.parse "20220216" +Integer.parse : Text -> Text -> Integer ! Parse_Error +Integer.parse text (radix=10) = + Panic.recover (Long.parseLong text radix) . catch _-> + Error.throw (Parse_Error text) + ## ALIAS From Text Parses a textual representation of a decimal into a decimal number, returning @@ -263,7 +282,7 @@ Number.to_json = Json.Number this > Example Parse the text "7.6" into a decimal number. - Decimal.parse 7.6 + Decimal.parse "7.6" Decimal.parse : Text -> Decimal ! Parse_Error Decimal.parse text = Panic.recover (Double.parseDouble text) . catch _-> diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Ordering/Natural_Order.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Ordering/Natural_Order.enso index ef855555371d..a365a18a7405 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Ordering/Natural_Order.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Ordering/Natural_Order.enso @@ -46,12 +46,8 @@ compare text1 text2 = pair = loop text next iter substring = Text_Utils.substring text prev pair.first - - ## TODO [RW] Currently there is no `Integer.parse` method, so we - parse a decimal and convert it to an integer. Once - https://www.pivotaltracker.com/story/show/181176522 is - implemented, this should be changed to use `Integer.parse`. - decimal = Decimal.parse substring . floor + + decimal = Integer.parse substring next_index = if pair.second then -1 else iter.current [substring, decimal, pair.first, next_index] diff --git a/test/Benchmarks/src/Natural_Order_Sort.enso b/test/Benchmarks/src/Natural_Order_Sort.enso index 133334048af1..bedadd5d30f0 100644 --- a/test/Benchmarks/src/Natural_Order_Sort.enso +++ b/test/Benchmarks/src/Natural_Order_Sort.enso @@ -1,8 +1,8 @@ from Standard.Base import all import Standard.Test.Bench - import Standard.Test.Faker + import Standard.Base.Data.Ordering.Natural_Order ## Bench Utilities ============================================================ diff --git a/test/Benchmarks/src/Number_Parse.enso b/test/Benchmarks/src/Number_Parse.enso new file mode 100644 index 000000000000..d5bdf1dd975c --- /dev/null +++ b/test/Benchmarks/src/Number_Parse.enso @@ -0,0 +1,41 @@ +from Standard.Base import all + +import Standard.Test.Bench +import Standard.Test.Faker + +## Bench Utilities ============================================================ + +make_double_strings : Integer -> Any -> Integer -> Integer -> Vector +make_double_strings count generator (min = -1000000000) (max = 1000000000) = + range = max - min + output = Array.new count + 0.up_to count . each i-> + v = generator.nextDouble * range - min + output.set_at i v.to_text + Vector.Vector output + +make_integer_strings : Integer -> Any -> Integer -> Integer -> Vector +make_integer_strings count generator (min = -1000000000) (max = 1000000000) = + range = max - min + output = Array.new count + 0.up_to count . each i-> + v = (generator.nextInt range - min) + output.set_at i v.to_text + Vector.Vector output + +vector_size = 1000000 +iter_size = 100 +num_iterations = 10 + +# The Benchmarks ============================================================== + +main = + ## No specific significance to this constant, just fixed to make generated set deterministic + fixed_random_seed = 1644575867 + random_generator = Faker.make_generator fixed_random_seed + + double_string = here.make_double_strings here.vector_size random_generator + Bench.measure (double_string.map Decimal.parse) "Decimal.parse" here.iter_size here.num_iterations + + int_strings = here.make_integer_strings here.vector_size random_generator + Bench.measure (int_strings.map Integer.parse) "Integer.parse" here.iter_size here.num_iterations diff --git a/test/Tests/src/Data/Numbers_Spec.enso b/test/Tests/src/Data/Numbers_Spec.enso index 3ae25b10d9cc..3d939b819bfb 100644 --- a/test/Tests/src/Data/Numbers_Spec.enso +++ b/test/Tests/src/Data/Numbers_Spec.enso @@ -173,6 +173,35 @@ spec = (negative_big_bits.bit_shift_r negative_big_bits).should_fail_with Arithmetic_Error negative_big_bits.bit_shift_r positive_big_bits . should_equal -1 + Test.specify "should be able to parse" <| + Integer.parse "1245623" . should_equal 1245623 + Integer.parse "012345" . should_equal 12345 + Integer.parse "-1234567" . should_equal -1234567 + Integer.parse "00000" . should_equal 0 + Integer.parse "00000123" . should_equal 123 + Integer.parse "123.45" . should_fail_with Parse_Error + Integer.parse "123A" . should_fail_with Parse_Error + Integer.parse "aaaa" . should_fail_with Parse_Error + + Test.specify "should be able to parse alternate bases" <| + Integer.parse "1245623" 8 . should_equal 347027 + Integer.parse "-1245623" 8 . should_equal -347027 + Integer.parse "0001245623" 8 . should_equal 347027 + Integer.parse "00000" 8 . should_equal 0 + Integer.parse "9847" 8 . should_fail_with Parse_Error + Integer.parse "8479" 8 . should_fail_with Parse_Error + Integer.parse "ABC123" 16 . should_equal 11256099 + Integer.parse "123ABC" 16 . should_equal 1194684 + Integer.parse "123aBc" 16 . should_equal 1194684 + Integer.parse "-ABC123" 16 . should_equal -11256099 + Integer.parse "00000ABC123" 16 . should_equal 11256099 + Integer.parse "123aBcG" 16 . should_fail_with Parse_Error + Integer.parse "10101010" 2 . should_equal 170 + Integer.parse "00001111" 2 . should_equal 15 + Integer.parse "-10101010" 2 . should_equal -170 + Integer.parse "-101021010" 2 . should_fail_with Parse_Error + Integer.parse "123" 128 . should_fail_with Parse_Error + Test.group "Decimals" <| Test.specify "should exist and expose basic arithmetic operations" <| @@ -183,6 +212,10 @@ spec = Test.specify "should be able to be parsed" <| Decimal.parse "32.5" . should_equal 32.5 + Decimal.parse "0122.5" . should_equal 122.5 + Decimal.parse "-98.5" . should_equal -98.5 + Decimal.parse "000000" . should_equal 0 + Decimal.parse "000000.0001" . should_equal 0.0001 Decimal.parse "aaaa" . should_fail_with Parse_Error Test.group "Numbers" <| @@ -229,3 +262,4 @@ spec = almost_max_long_times_three_decimal.ceil.to_decimal . should_equal almost_max_long_times_three_plus_1.to_decimal almost_max_long_times_three_plus_1.ceil . should_equal almost_max_long_times_three_plus_1 +main = Test.Suite.run_main here.spec