From 9585080ab80f41eb1cf89d7349be8c4559fe914c Mon Sep 17 00:00:00 2001 From: Ara Adkins Date: Thu, 1 Apr 2021 12:20:36 +0100 Subject: [PATCH] Clean up the standard library docs (#1641) --- .github/CODEOWNERS | 62 +-- distribution/std-lib/Standard/package.yaml | 2 +- .../src/Base/Data/Any/Extensions.enso | 167 ++++-- .../src/Base/Data/Array/Extensions.enso | 16 +- .../Standard/src/Base/Data/Interval.enso | 17 + .../src/Base/Data/Interval/Bound.enso | 21 +- .../std-lib/Standard/src/Base/Data/Json.enso | 115 ++++- .../Standard/src/Base/Data/Json/Internal.enso | 197 ++++++- .../std-lib/Standard/src/Base/Data/List.enso | 60 ++- .../Standard/src/Base/Data/Locale.enso | 169 +++++- .../std-lib/Standard/src/Base/Data/Map.enso | 130 ++++- .../Standard/src/Base/Data/Map/Internal.enso | 50 +- .../std-lib/Standard/src/Base/Data/Maybe.enso | 3 + .../std-lib/Standard/src/Base/Data/Noise.enso | 4 + .../src/Base/Data/Noise/Generator.enso | 28 +- .../src/Base/Data/Number/Extensions.enso | 130 ++++- .../Standard/src/Base/Data/Ordering.enso | 7 +- .../src/Base/Data/Ordering/Sort_Order.enso | 2 + .../std-lib/Standard/src/Base/Data/Pair.enso | 8 + .../std-lib/Standard/src/Base/Data/Range.enso | 39 +- .../src/Base/Data/Text/Extensions.enso | 280 ++++++++-- .../src/Base/Data/Text/Split_Kind.enso | 6 +- .../Standard/src/Base/Data/Time/Date.enso | 120 +++-- .../Standard/src/Base/Data/Time/Duration.enso | 97 +++- .../Standard/src/Base/Data/Time/Time.enso | 228 ++++++--- .../src/Base/Data/Time/Time_Of_Day.enso | 126 +++-- .../Standard/src/Base/Data/Time/Zone.enso | 49 +- .../Standard/src/Base/Data/Vector.enso | 297 ++++++++--- .../Standard/src/Base/Error/Extensions.enso | 64 ++- .../std-lib/Standard/src/Base/Math.enso | 26 + .../std-lib/Standard/src/Base/Meta.enso | 292 ++++++++--- .../Standard/src/Base/Meta/Enso_Project.enso | 8 + .../Standard/src/Base/Network/Http.enso | 310 +++++++---- .../Standard/src/Base/Network/Http/Form.enso | 47 ++ .../src/Base/Network/Http/Header.enso | 78 ++- .../src/Base/Network/Http/Method.enso | 15 + .../src/Base/Network/Http/Request.enso | 174 +++++-- .../src/Base/Network/Http/Request/Body.enso | 15 + .../src/Base/Network/Http/Response.enso | 9 +- .../src/Base/Network/Http/Response/Body.enso | 12 +- .../src/Base/Network/Http/Status_Code.enso | 5 +- .../Standard/src/Base/Network/Internal.enso | 9 + .../Standard/src/Base/Network/Proxy.enso | 16 +- .../Standard/src/Base/Network/Uri.enso | 100 +++- .../src/Base/Network/Uri/Internal.enso | 5 + .../Standard/src/Base/Polyglot/Java.enso | 8 +- .../Standard/src/Base/System/Environment.enso | 7 + .../Standard/src/Base/System/File.enso | 386 +++++++++----- .../Standard/src/Base/System/File/Option.enso | 11 + .../Standard/src/Base/System/Platform.enso | 32 +- .../Standard/src/Base/System/Process.enso | 52 +- .../src/Base/System/Process/Exit_Code.enso | 21 +- .../src/Database/Connection/Connection.enso | 78 ++- .../src/Database/Connection/Database.enso | 51 +- .../Standard/src/Database/Data/Column.enso | 267 +++++++--- .../Standard/src/Database/Data/Dialect.enso | 10 +- .../Data/Internal/Base_Generator.enso | 69 ++- .../src/Database/Data/Internal/Helpers.enso | 25 +- .../src/Database/Data/Internal/IR.enso | 80 ++- .../Data/Internal/Vector_Builder.enso | 19 + .../Standard/src/Database/Data/Sql.enso | 142 +++-- .../Standard/src/Database/Data/Table.enso | 227 +++++--- .../std-lib/Standard/src/Geo/Geo_Json.enso | 4 + .../std-lib/Standard/src/Image/Codecs.enso | 39 +- .../Standard/src/Image/Data/Histogram.enso | 6 +- .../Standard/src/Image/Data/Image.enso | 39 +- .../src/Image/Data/Image/Internal.enso | 13 + .../Standard/src/Image/Data/Matrix.enso | 67 ++- .../src/Image/Data/Matrix/Internal.enso | 12 + distribution/std-lib/Standard/src/Main.enso | 3 + distribution/std-lib/Standard/src/Table.enso | 20 +- .../Standard/src/Table/Data/Column.enso | 345 +++++++++---- .../Standard/src/Table/Data/Order_Rule.enso | 41 +- .../Standard/src/Table/Data/Storage.enso | 10 + .../Standard/src/Table/Data/Table.enso | 247 ++++++--- .../src/Table/Internal/Java_Exports.enso | 6 + .../std-lib/Standard/src/Table/Io/Csv.enso | 14 +- distribution/std-lib/Standard/src/Test.enso | 484 ++++++++++++------ .../std-lib/Standard/src/Test/Bench.enso | 54 +- .../src/Visualization/Sql/Visualization.enso | 8 + .../Visualization/Table/Visualization.enso | 7 + .../interpreter/epb/node/ForeignEvalNode.java | 13 +- .../runtime/src/main/resources/Builtins.enso | 41 +- test/Database_Tests/src/Main.enso | 2 +- test/Database_Tests/src/Sqlite_Spec.enso | 2 +- test/Geo_Tests/src/Main.enso | 2 +- test/Image_Tests/src/Main.enso | 2 +- test/Table_Tests/src/Main.enso | 2 +- test/Tests/src/Main.enso | 2 +- test/Visualization_Tests/src/Main.enso | 2 +- 90 files changed, 4955 insertions(+), 1632 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index f2b1de62a6..880ec8be45 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -2,52 +2,52 @@ * @iamrecursion @kustosz @radeusgd # Distribution -/distribution @iamrecursion @kustosz @radeusgd -/distribution/std-lib @iamrecursion @kustosz @wdanilo +/distribution @iamrecursion @kustosz @radeusgd @4e6 +/distribution/std-lib @iamrecursion @kustosz @wdanilo @4e6 # Scala Libraries -/lib/scala/cli @iamrecursion @kustosz @radeusgd -/lib/scala/core-definition @iamrecursion @kustosz -/lib/scala/flexer @iamrecursion @kustosz -/lib/scala/graph @iamrecursion @kustosz -/lib/scala/interpreter-dsl @iamrecursion @kustosz +/lib/scala/cli @iamrecursion @kustosz @radeusgd @4e6 +/lib/scala/core-definition @iamrecursion @kustosz @4e6 +/lib/scala/flexer @iamrecursion @kustosz @4e6 +/lib/scala/graph @iamrecursion @kustosz @4e6 +/lib/scala/interpreter-dsl @iamrecursion @kustosz @4e6 /lib/scala/json-rpc-server @radeusgd @4e6 @iamrecursion @kustosz /lib/scala/json-rpc-server-test @radeusgd @4e6 @iamrecursion @kustosz -/lib/scala/logger @kustosz @iamrecursion -/lib/scala/parser-service @kustosz @iamrecursion -/lib/scala/pkg @iamrecursion @kustosz +/lib/scala/logger @kustosz @iamrecursion @4e6 +/lib/scala/parser-service @kustosz @iamrecursion @4e6 +/lib/scala/pkg @iamrecursion @kustosz @4e6 /lib/scala/project-manager @radeusgd @4e6 @kustosz -/lib/scala/searcher @4e6 @radeusgd @kustosz -/lib/scala/syntax @iamrecursion @kustosz +/lib/scala/searcher @4e6 @radeusgd @kustosz @iamrecursion +/lib/scala/syntax @iamrecursion @kustosz @4e6 /lib/scala/testkit @4e6 @kustosz @iamrecursion -/lib/scala/text-buffer @iamrecursion @kustosz -/lib/scala/version-output @iamrecursion @kustosz @radeusgd +/lib/scala/text-buffer @iamrecursion @kustosz @4e6 +/lib/scala/version-output @iamrecursion @kustosz @radeusgd @4e6 # Rust Libraries /lib/rust/ @iamrecursion @wdanilo @radeusgd # Main Project -/engine/language-server @radeusgd @4e6 @kustosz -/engine/launcher @iamrecursion @kustosz @radeusgd -/engine/polyglot-api @iamrecursion @kustosz -/engine/runner @iamrecursion @kustosz @radeusgd -/engine/runtime @iamrecursion @kustosz @radeusgd +/engine/language-server @radeusgd @4e6 @kustosz @iamrecursion +/engine/launcher @iamrecursion @kustosz @radeusgd @4e6 +/engine/polyglot-api @iamrecursion @kustosz @4e6 +/engine/runner @iamrecursion @kustosz @radeusgd @4e6 +/engine/runtime @iamrecursion @kustosz @radeusgd @4e6 # Documentation -/docs @iamrecursion @kustosz -/.gitignore @iamrecursion @kustosz -/.jvmopts @iamrecursion @kustosz -/.scalafmt.conf @iamrecursion @kustosz -/CODE_OF_CONDUCT.md @iamrecursion @kustosz -/LICENSE @iamrecursion @kustosz -README.md @iamrecursion @kustosz +/docs @iamrecursion @kustosz @4e6 +/.gitignore @iamrecursion @kustosz @4e6 +/.jvmopts @iamrecursion @kustosz @4e6 +/.scalafmt.conf @iamrecursion @kustosz @4e6 +/CODE_OF_CONDUCT.md @iamrecursion @kustosz @4e6 +/LICENSE @iamrecursion @kustosz @4e6 +README.md @iamrecursion @kustosz @4e6 # Config -/.github @iamrecursion @kustosz -/.github/workflows @iamrecursion @kustosz @radeusgd -/tools @iamrecursion @kustosz @radeusgd -/project @iamrecursion @kustosz @radeusgd -/build.sbt @iamrecursion @kustosz @radeusgd +/.github @iamrecursion @kustosz @4e6 +/.github/workflows @iamrecursion @kustosz @radeusgd @4e6 +/tools @iamrecursion @kustosz @radeusgd @4e6 +/project @iamrecursion @kustosz @radeusgd @4e6 +/build.sbt @iamrecursion @kustosz @radeusgd @4e6 # Repo Configuration /.github/settings.yml @iamrecursion diff --git a/distribution/std-lib/Standard/package.yaml b/distribution/std-lib/Standard/package.yaml index f026aa611c..2923e3659b 100644 --- a/distribution/std-lib/Standard/package.yaml +++ b/distribution/std-lib/Standard/package.yaml @@ -1,6 +1,6 @@ license: APLv2 name: Standard enso-version: default -version: "0.0.1" +version: "0.1.0" author: "Enso Team " maintainer: "Enso Team " diff --git a/distribution/std-lib/Standard/src/Base/Data/Any/Extensions.enso b/distribution/std-lib/Standard/src/Base/Data/Any/Extensions.enso index 13812b5876..0d1fd141de 100644 --- a/distribution/std-lib/Standard/src/Base/Data/Any/Extensions.enso +++ b/distribution/std-lib/Standard/src/Base/Data/Any/Extensions.enso @@ -3,10 +3,24 @@ from Standard.Base import all ## Checks if `this` is equal to `that.` Arguments: - - that: The object to compare `this` against. + - that: The object to compare `this` with. - Two values are considered to be equal in Enso when they have the same - structure, and each of the values of their fields are recursively equal. + Two values are considered to be equal in Enso when they obey the following + recursive properties: + - At each level, they have the same structure. + - The value of each field in `this` is equal (by this definition) to the + corresponding field in `that`. + + ! Implementing Your Own Equality + Equality in Enso is defined to allow comparison of any two values + (universal equality), no matter if they are not directly comparable. When + implementing equality for your own types, keep in mind that it needs to + work with any Enso value as the `that` argument. + + ? Generic Equality and Performance + While the generic equality provided here will work for _all_ values in + Enso, its performance may often be suboptimal. Many types can implement + their own equality operations that will be more efficient than these. > Example Checking if 1 is equal to 2. @@ -29,7 +43,7 @@ Any.== that = if Meta.is_same_object this that then True else if langs_match.not then False else o_1.equals o_2 ## Constructor comparison is covered by the identity equality. Primitive objects should define their own equality. - Therefore, there is no more cases to handle in this method. + Therefore, there are no more cases to handle in this method. _ -> False ## Checks if `this` is not equal to `that`. @@ -37,6 +51,11 @@ Any.== that = if Meta.is_same_object this that then True else Arguments: - that: The object to compare `this` against. + ! Implementing Your Own Inequality + We recommend that you do not implement your own inequality, instead relying + on the default definition given here. If you do, please ensure that you + satisfy universal equality, as described in the documentation for `Any.==`. + > Example Checking if 1 is not equal to 2. 1 != 2 @@ -45,53 +64,111 @@ Any.!= that = (this == that).not ## Checks if `this` is greater than `that`. + Arguments: + - that: The value to compare `this` against. + To have `>` defined, a type must define `compare_to`, returning an Ordering. + ! Implementing Greater Than + Many types can admit a definition of greater than that is more efficient + than the generic one given here. When implementing this for your own types + please ensure that it is semantically equivalent to using `.compare_to`. + > Example - Compare two integers. - 1 > 10 == False + Checking if 1 is greater than 10. + 1 > 10 Any.> : Any -> Boolean Any.> that = this.compare_to that == Ordering.Greater +## Checks if `this` is greater than or equal to `that`. + + Arguments: + - that: The value to compare `this` against. + + To have `>=` defined, a type must define both `>` and `==`. + + ! Implementing Greater Than or Equal + While it is often possible to implement a more efficient version of this + operation for complex types, care must be taken to ensure that your + implementation is semantically equivalent to the disjunction of the + greater than and equal to operations. + + > Example + Checking if 1 is greater than or equal to 10. + 1 >= 10 +Any.>= : Any -> Boolean +Any.>= that = (this > that) || (this == that) + ## Checks if `this` is less than `that`. + Arguments: + - that: The value to compare `this` against. + To have `<` defined, a type must define `compare_to`, returning an Ordering. + ! Implementing Less Than + Many types can admit a definition of less than that is more efficient than + the generic one given here. When implementing this for your own types + please ensure that it is semantically equivalent to using `.compare_to`. + > Example - Compare two integers. - 1 < 10 == True + Checking if 1 is less than 10. + 1 < 10 Any.< : Any -> Boolean Any.< that = this.compare_to that == Ordering.Less -## Checks if the type is an instance of `Nothing`. +## Checks if `this` is less than or equal to `that`. + + Arguments: + - that: The value to compare `this` against. + + To have `<=` defined, a type must define both `<` and `==`. + + ! Implementing Less Than or Equal + While it is often possible to implement a more efficient version of this + operation for complex types, care must be taken to ensure that your + implementation is semantically equivalent to the disjunction of the + less than than and equal to operations. > Example - Checking if a variable `a` is nothing. - a.is_nothing + Checking if 1 is less than or equal to 10. + 1 <= 10 +Any.<= : Any -> Boolean +Any.<= that = (this < that) || (this == that) + +## Checks if the type is an instance of `Nothing`. + + Nothing in Enso is used as a universal value to indicate the lack of presence + of a value. This function is primarily useful in the IDE. + + > Example + Checking if the value 1 is nothing. + 1.is_nothing Any.is_nothing : Boolean Any.is_nothing = case this of Nothing -> True _ -> False -## Executes the provided handler on a dataflow error, or executes as identity on - a non-error value. +## Executes the provided handler on a dataflow error, or returns a non-error + value unchanged. Arguments: - handler: The function to call on this if it is an error value. By default this is identity. > Example - Catching an erroneous value to perform some operation on it. - (Time.Time_Error "Message").catch (err -> IO.println err) + Catching an erroneous value and getting the length of its message. + (Time.Time_Error "Message").catch (err -> err.error_message.length) Any.catch : (Error -> Any) -> Any Any.catch (handler = x->x) = this.catch_primitive handler -## Maps a dataflow error. - If the original value was a non-error value, it is not affected, but if it - was an error, the error is mapped through the provided function. +## Transforms an error. Arguments: - - f: The function to transform the error. + - f: The function used to transform the error. + + If `this` is a non-error value it is returned unchanged. However, if `this` + is an error, the error is transformed using the provided function. > Example Wrapping an error value. @@ -99,7 +176,7 @@ Any.catch (handler = x->x) = this.catch_primitive handler Any.map_error : (Error -> Error) -> Any Any.map_error _ = this -## Checks if the underlying value is an error. +## Checks if `this` is an error. Any.is_error : Boolean Any.is_error = False @@ -108,6 +185,11 @@ Any.is_error = False Arguments: - argument: The argument to apply `this` to. + ? Piping Blocks to Functions + This construction is particularly useful for passing a block as an argument + to a function. This means that you can compute more sophisticated values + in-line, as shown in the example below. + > Example Applying a function to a block. (x -> x + 1) <| @@ -121,28 +203,35 @@ Any.<| ~argument = this argument Arguments - function: The function to apply to `this`. + ? `|>` or `.`? + The eagle-eyed reader will notice that the operator dot (`.`) is very + similar to the operator `|>`. In Enso, with the variable precedence of + operators, this makes perfect sense. In general, we recommend using `.`. + However, there are some contexts where variable precedence might be unclear + or confusing, or where the function being applied is not a method. In these + contexts we recommend using `|>`. + > Example - Applying a function in a pipeline. - 1 |> (* 2) + Applying multiple functions in a pipeline to compute a number and transform + it to text. + 1 |> (* 2) |> (/ 100) |> .to_text Any.|> : (Any -> Any) -> Any -Any.|> function = function this +Any.|> ~function = function this -## Composes two functions together. - - For `f << g`, this creates the function composition `f ∘ g`. +## Composes two functions together, for `f << g` creating the function + composition `f ∘ g` (equivalent to `x -> f (g x)`). Arguments: - that: The function to compose with `this`. > Example - Compose the functions +1 and *2 and apply it to 2 + Multiply by 2 and then add 1 as a function applied to 2. (+1 << *2) 2 Any.<< : (Any -> Any) -> (Any -> Any) -> Any -> Any -Any.<< that = x -> this (that x) +Any.<< ~that = x -> this (that x) -## Composes two functions together in the forward direction. - - For `f >> g`, this creates the function composition `g ∘ f`. +## Composes two functions together in the forward direction, for `f >> g` + creating the function composition `g ∘ f` (equivalent to `x -> g (f (x))`). Arguments: - that: The function to compose with `this`. @@ -151,16 +240,22 @@ Any.<< that = x -> this (that x) Add one and then multiply by two as a function applied to 2. (+1 >> *2) 2 Any.>> : (Any -> Any) -> (Any -> Any) -> Any -> Any -Any.>> that = x -> that (this x) +Any.>> ~that = x -> that (this x) ## UNSTABLE ADVANCED - Returns a Text used to display this value in the IDE. The particular - representation is left unspecified and subject to change in the future. - The current implementation uses a JSON serialization as the default. + Returns a Text used to display this value in the IDE. + + The particular representation is left unspecified and subject to change in + the future. The current implementation uses JSON serialization as the + default. Types defining their own versions of this method should ensure that the - result is reasonably small and the operation is quick to compute. + result is reasonably small and that the operation is quick to compute. + + > Example + Converting the number `2` into visualization data. + 2.to_default_visualization_data Any.to_default_visualization_data : Text Any.to_default_visualization_data = this.to_json.to_text diff --git a/distribution/std-lib/Standard/src/Base/Data/Array/Extensions.enso b/distribution/std-lib/Standard/src/Base/Data/Array/Extensions.enso index e6ddc39cf7..137ee2ec37 100644 --- a/distribution/std-lib/Standard/src/Base/Data/Array/Extensions.enso +++ b/distribution/std-lib/Standard/src/Base/Data/Array/Extensions.enso @@ -1,8 +1,18 @@ from Standard.Base import all -## Transform the array into text for displaying as part of its default - visualization. +## UNSTABLE + ADVANCED + + Returns a Text used to display this value in the IDE. + + The particular representation is left unspecified and subject to change in + the future. The current implementation uses JSON serialization as the + default. + + > Example + Converting an array to its default visualization representation. + [1, 2, 3, 4].to_array.to_default_visualization_data Array.to_default_visualization_data : Text -Array.to_default_visualization_data = +Array.to_default_visualization_data = Vector.Vector this . to_default_visualization_data diff --git a/distribution/std-lib/Standard/src/Base/Data/Interval.enso b/distribution/std-lib/Standard/src/Base/Data/Interval.enso index 485b8dcca9..ae3753a0ac 100644 --- a/distribution/std-lib/Standard/src/Base/Data/Interval.enso +++ b/distribution/std-lib/Standard/src/Base/Data/Interval.enso @@ -38,10 +38,19 @@ inclusive start end = Interval (Bound.Inclusive start) (Bound.Inclusive end) ## An interval type type Interval + + ## A type representing an interval over orderable types. + + Arguments: + - start: The start of the interval. + - end: The end of the interval. type Interval start end ## Checks if the interval contains `that`. + Arguments: + - that: The item to check if it is contained in the interval. + > Example Checking if the interval 1 to 5 contains 7. (Interval.inclusive 1 5) . contains 7 @@ -56,6 +65,10 @@ type Interval Bound.Inclusive e -> that <= e ## Check if this interval is empty. + + > Example + Check if the interval from 0 to 0 is empty. + Interval.inclusive 0 0 . is_empty is_empty : Boolean is_empty = case this.start of Bound.Exclusive s -> case this.end of @@ -66,6 +79,10 @@ type Interval Bound.Inclusive e -> s > e ## Check if this interval is not empty. + + > Example + Check if the interval from 0 to 1 is not empty. + Interval.inclusive 0 1 . not_empty not_empty : Boolean not_empty = this.is_empty.not diff --git a/distribution/std-lib/Standard/src/Base/Data/Interval/Bound.enso b/distribution/std-lib/Standard/src/Base/Data/Interval/Bound.enso index 9e596b9080..21a46d7f49 100644 --- a/distribution/std-lib/Standard/src/Base/Data/Interval/Bound.enso +++ b/distribution/std-lib/Standard/src/Base/Data/Interval/Bound.enso @@ -2,10 +2,25 @@ from Standard.Base import all ## A type representing an interval bound over any orderable type. - An orderable type is one that + An orderable type is one that has a + [total order](https://en.wikipedia.org/wiki/Total_order) defined for it. type Bound - ## A bound that includes `n`. + ## A bound that includes the value `n`. + + Arguments: + - n: The value defining the inclusive bound. + + > Example + Create a bound that includes the value 2. + Inclusive 2 type Inclusive n - ## A bound that excludes `n`. + ## A bound that excludes the value `n`. + + Arguments: + - n: The value defining the exclusive bound. + + > Example + Create a bound that excludes the value 2. + Exclusive 2 type Exclusive n diff --git a/distribution/std-lib/Standard/src/Base/Data/Json.enso b/distribution/std-lib/Standard/src/Base/Data/Json.enso index b403e5d964..7170d39eeb 100644 --- a/distribution/std-lib/Standard/src/Base/Data/Json.enso +++ b/distribution/std-lib/Standard/src/Base/Data/Json.enso @@ -4,19 +4,47 @@ import Standard.Base.Data.Json.Internal ## Represents a JSON structure. type Json + + ## A representation of a JSON object. + + Arguments: + - fields: The fields of the JSON object. type Object fields + + ## A representation of a JSON array. + + Arguments: + - items: The items in the JSON array. type Array items + + ## A representation of a JSON string. + + Arguments: + - value: The text contained in the JSON string. type String value + + ## A representation of a JSON number. + + Arguments: + - value: The number contained in the JSON number. type Number value + + ## A representation of a JSON boolean. + + Arguments: + - value: The boolean contained in a JSON boolean. type Boolean value + + ## A representation of a JSON null. type Null ## Marshalls this JSON into an arbitrary value described by `type_descriptor`. - The type descriptor is a fully-applied type, describing all required - sub-types. It can either be an Atom or one of the primitive types - (`Number`, `Text`, `Boolean`, `Vector`). + Arguments: + - `type_dscriptor`: The type descriptor is a fully-applied type, + describing all required sub-types. It can either be an Atom or one of + the primitive types (`Number`, `Text`, `Boolean`, `Vector`). > Example The following shows an example of reading a nested JSON into a desired @@ -63,10 +91,18 @@ type Json to_json = this ## Renders this JSON into an RFC-8259 compliant text. + + > Example + Convert a JSON number to text. + Json.Number 3 . to_text to_text : Text to_text = Internal.render_helper "" this ## Recursively unwraps the JSON value into primitive values. + + > Example + Unwrap the JSON number 3 to the primitive number 3. + Json.Number 3 . unwrap unwrap : Any unwrap = case this of Json.Array its -> its.map .unwrap @@ -76,21 +112,36 @@ type Json Json.Null -> Nothing Json.Object f -> f.map .unwrap -## A failure indicating malformed text input into the JSON parser. +## UNSTABLE + + A failure indicating malformed text input into the JSON parser. Check the `message` field for detailed information on the specific failure. type Parse_Error message -## Converts the error to a display representation. +## UNSTABLE + + Converts the error to a display representation. Parse_Error.to_display_text : Text Parse_Error.to_display_text = "Parse error in parsing JSON: " + this.message.to_text + "." -## Gets the value associated with the given key in this object. Returns - `Nothing` if the associated key is not defined. -Object.get : Text -> Json | Nothing +## Gets the value associated with the given key in this object. + + Arguments: + - field: The name of the field from which to get the value. + + Throws `Nothing` if the associated key is not defined. +Object.get : Text -> Json ! Nothing Object.get field = this.fields.get field ## Parses an RFC-8259 compliant JSON text into a `Json` structure. + + Arguments: + - json_text: The RFC-8259-compliant JSON text. + + > Example + Convert some text representing a JSON object into JSON. + "{ "a": 1 }".parse parse : Text -> Json ! Parse_Error parse json_text = r = Panic.recover (Internal.parse_helper json_text) @@ -98,22 +149,41 @@ parse json_text = Polyglot_Error err -> Error.throw (Parse_Error err.getMessage) p -> Panic.throw p -## A failure indicating the inability to marshall a `Json` object into the +## UNSTABLE + + A failure indicating the inability to marshall a `Json` object into the specified format. type Marshalling_Error - ## The `json` object could not be converted into `format`, due to a type + + ## UNSTABLE + + The `json` object could not be converted into `format`, due to a type mismatch. + Arguments: + - json: The JSON that could not be marshalled. + - format: The type format that did not match. + This can occur e.g. when trying to reinterpret a number as a `Text`, etc. type Type_Mismatch_Error json format - ## The `json` object could not be converted into `format`, due to a field + ## UNSTABLE + + The `json` object could not be converted into `format`, due to a field missing in the `json` structure. + Arguments: + - json: The json that had a missing field. + - field: The field name that was missing. + - format: The type format that diud not match. + This can occure when trying to reinterpret a JSON object into an atom, when the JSON does not contain all the fields required by the atom. type Missing_Field_Error json field format + ## UNSTABLE + + Convert the marshalling error into a human-readable format. to_display_text : Text to_display_text = case this of Type_Mismatch_Error json format -> @@ -128,6 +198,10 @@ type Marshalling_Error The input atom is converted into a JSON object, with a `"type"` field set to the atom's type name and all other fields serialized with their name as object key and the value as the object value. + + > Example + Convert a vector to JSON. + [1, 2, 3, 4].to_json Any.to_json = m = Meta.meta this case m of @@ -147,20 +221,35 @@ Any.to_json = Meta.Primitive _ -> Null ## Method used by object builders to convert a value into a valid JSON key. + + > Example + Ensure that the text "foo" is a JSON key. + "foo".to_json_key Text.to_json_key : Text Text.to_json_key = this -## Boolean to JSON conversion. +## Convert a boolean to JSON. + + > Example + Convert `True` to JSON. + True.to_json Base.Boolean.to_json : Boolean Base.Boolean.to_json = Boolean this -## Nothing to JSON conversion. +## Convert `Nothing` to JSON. + + > Example + Convert `Nothing` to JSON. + Nothing.to_json Nothing.to_json : Null Nothing.to_json = Null ## A smart constructor, building an object representation based on a vector of key-value pairs. + Arguments: + - contents: A vector of key-value pairs. + All values used as keys must define a `to_json_key : Text` method. > Example diff --git a/distribution/std-lib/Standard/src/Base/Data/Json/Internal.enso b/distribution/std-lib/Standard/src/Base/Data/Json/Internal.enso index adfa658401..b206042c98 100644 --- a/distribution/std-lib/Standard/src/Base/Data/Json/Internal.enso +++ b/distribution/std-lib/Standard/src/Base/Data/Json/Internal.enso @@ -5,19 +5,40 @@ from Standard.Base.Data.Json import all polyglot java import org.enso.base.json.Parser polyglot java import org.enso.base.json.Printer -## A JSON parser event consumer, passed to the Java parser backend. +## PRIVATE + + A JSON parser event consumer, passed to the Java parser backend. Conforms to the `org.enso.base.json.Parser.JsonConsumer` Java interface. type Consumer + + ## PRIVATE + + A JSON parser event consumer, passed to the Java parser backend. + + Arguments: + - child_consumer: The child consumer of this. + - value: The value being consumed. + + Conforms to the `org.enso.base.json.Parser.JsonConsumer` Java interface. type Consumer child_consumer value - ## Helper for handling "value emitted" events. + ## PRIVATE + + A helper for handling "value emitted" events. + + Arguments: + - v: The value to act upon. + on_value : Any -> Nothing on_value v = case Ref.get this.child_consumer of Nil -> Ref.put this.value v cons -> cons.on_value v - ## Closes the child consumer and either sets the current consumer to its + ## PRIVATE + + Closes the child consumer and either sets the current consumer to its parent, or takes its returned value as the final result of parsing. + seal_child : Nothing seal_child = child = Ref.get this.child_consumer val = child.seal @@ -28,92 +49,202 @@ type Consumer Ref.put this.child_consumer p p.on_value val - ## Consumes the `start_object` event. + ## PRIVATE + + Consumes the `start_object` event. + on_start_object : Nothing on_start_object = parent = Ref.get this.child_consumer Ref.put this.child_consumer (here.mk_object_consumer parent) - ## Consumes the `key` event. + ## PRIVATE + + Consumes the `key` event. + + Arguments: + - k: The key to act upon. + on_key : Text -> Nothing on_key k = Ref.get this.child_consumer . on_key k - ## Consumes the `end_object` event. + ## PRIVATE + + Consumes the `end_object` event. + on_end_object : Nothing on_end_object = this.seal_child - ## Consumes the `start_array` event. + ## PRIVATE + + Consumes the `start_array` event. + on_start_array : Nothing on_start_array = parent = Ref.get this.child_consumer Ref.put this.child_consumer (here.mk_array_consumer parent) - ## Consumes the `end_array` event. + ## PRIVATE + + Consumes the `end_array` event. + on_end_array : Nothing on_end_array = this.seal_child - ## Consumes the `long` event. + ## PRIVATE + + Consumes the `long` event. + + Arguments: + - n: The long value to process. + on_long : Integer -> Nothing on_long n = this.on_value (Number n) - ## Consumes the `double` event. + ## PRIVATE + + Consumes the `double` event. + + Arguments: + - n: The double value to process. + on_double : Decimal -> Nothing on_double n = this.on_value (Number n) - ## Consumes the `string` event. + ## PRIVATE + + Consumes the `string` event. + + Arguments: + - s: The string value to process. + on_string : Text -> Nothing on_string s = this.on_value (String s) - ## Consumes the `true` event. + ## PRIVATE + + Consumes the `true` event. + on_true : Nothing on_true = this.on_value (Boolean True) - ## Consumes the `false` event. + ## PRIVATE + + Consumes the `false` event. + on_false : Nothing on_false = this.on_value (Boolean False) - ## Consumes the `null` event. + ## PRIVATE + + Consumes the `null` event. + on_null : Nothing on_null = this.on_value Null -## A child consumer, used to process events inside arrays. +## PRIVATE + + A child consumer, used to process events inside arrays. type Array_Consumer + ## PRIVATE + + A child consumer, used to process events inside arrays. + + Arguments: + - builder: The builder for array values. + - parent: The parent consumer. type Array_Consumer builder parent - ## Consumes a value. + ## PRIVATE + + Consumes a value. + + Arguments: + - v: The value to process. + on_value : Any -> Nothing on_value v = this.builder.append v - ## Returns the final value built by this consumer. + ## PRIVATE + + Returns the final value built by this consumer. + seal : Array seal = vec = this.builder.to_vector Array vec -## A child consumer, used to process events inside objects. +## PRIVATE + + A child consumer, used to process events inside objects. type Object_Consumer + ## PRIVATE + + A child consumer, used to process events inside objects. + + Arguments: + - last_key: The last object key that has been seen. + - map: The map representing the object. + - parent: The parent consumer. type Object_Consumer last_key map parent - ## Consumes a key. + ## PRIVATE + + Consumes a key. + + Arguments: + - k: The key to process. + on_key : Text -> Nothing on_key k = Ref.put this.last_key k - ## Consumes a value. + ## PRIVATE + + Consumes a value. + + Arguments: + - v: The value to process. + on_value : Any -> Nothing on_value v = k = Ref.get this.last_key m = Ref.get this.map new_m = m.insert k v Ref.put this.map new_m - ## Returns the final value built by this consumer. + ## PRIVATE + + Returns the final value built by this consumer. + seal : Object seal = m = Ref.get this.map Object m -## Creates a new object consumer with the given parent. +## PRIVATE + + Creates a new object consumer with the given parent. + + Arguments: + - parent: The parent of the new consumer. +mk_object_consumer : Any -> Object_Consumer mk_object_consumer parent = k = Ref.new "" m = Ref.new Map.empty Object_Consumer k m parent -## Creates a new array consumer with the given parent. +## PRIVATE + + Creates a new array consumer with the given parent. + + Arguments: + - parent: The parent of the new consumer. +mk_array_consumer : Any -> Array_Consumer mk_array_consumer parent = bldr = Vector.new_builder Array_Consumer bldr parent -## Creates a new top-level consumer. +## PRIVATE + + Creates a new top-level consumer. +mk_consumer : Consumer mk_consumer = child = Ref.new Nil val = Ref.new Nothing Consumer child val -## Helper method for printing JSON values to Text. +## PRIVATE + + A helper method for printing JSON values to Text. + + Arguments: + - builder: An accumulator for text. + - json: The json value being converted to text. +render_helper : Text -> Json -> Text render_helper builder json = case json of Object fields -> r = Ref.new "" @@ -143,9 +274,16 @@ render_helper builder json = case json of Null -> builder + "null" -## Helper method for converting JSON objects into arbitrary types. +## PRIVATE + + A helper method for converting JSON objects into arbitrary types. + + Arguments: + - fmt: The format to convert the JSON into. + - json: The JSON being converted. See `Json.into` for semantics documentation. +into_helper : Any -> Json -> Any into_helper fmt json = case fmt of Base.Vector.Vector field -> case json of Array items -> items.map (here.into_helper field) @@ -175,7 +313,12 @@ into_helper fmt json = case fmt of _ -> Panic.throw (Type_Mismatch_Error json fmt) _ -> Panic.throw (Type_Mismatch_Error json fmt) -## Helper used to parse text into a JSON value. +## PRIVATE + + A helper used to parse text into a JSON value. + + Arguments: + - json_text: The textual representation of the JSON. parse_helper : Text -> Json parse_helper json_text = consumer = here.mk_consumer diff --git a/distribution/std-lib/Standard/src/Base/Data/List.enso b/distribution/std-lib/Standard/src/Base/Data/List.enso index 5a468d6896..babdd0c35b 100644 --- a/distribution/std-lib/Standard/src/Base/Data/List.enso +++ b/distribution/std-lib/Standard/src/Base/Data/List.enso @@ -4,6 +4,11 @@ from Builtins export Nil, Cons ## PRIVATE A helper for the `map` function. + Arguments: + - list: The list to map over. + - cons: The current field to set. + - f: The function to apply to the value. + Uses unsafe field mutation under the hood, to rewrite `map` in a tail-recursive manner. The mutation is purely internal and does not leak to the user-facing API. @@ -16,7 +21,7 @@ map_helper list cons f = case list of ## The basic cons-list type. - A cons-list allows to store an arbitrary number of elements. + A cons-list allows storage of an arbitrary number of elements. Prepending to the list can be achieved by using the `Cons` constructor, while an empty list is represented by `Nil`. @@ -29,12 +34,20 @@ type List Cons ## Computes the number of elements in the list. + + > Example + Get the length of a two item list. + (Cons 1 (Cons 2 Nil)).length length : Number length = this.fold 0 (acc -> _ -> acc + 1) ## Combines all the elements of the list, by iteratively applying the passed function with next elements of the list. + Arguments: + - init: The initial value for the fold. + - f: The binary function used to combine elements of the list. + In general, the result of (Cons l0 <| Cons l1 <| ... <| Cons ln) . fold init f is the same as @@ -54,8 +67,10 @@ type List ## Checks whether any element of the list matches the given predicate. - A predicate is a function that takes a list element and returns - a Boolean value. + Arguments: + - predicate: A function that takes a list element and returns a boolean + value that says whether that value satisfies the conditions of the + function. > Example In the following example, we'll check if any element of the list is @@ -72,6 +87,11 @@ type List ## Checks whether any element of the list matches the given predicate. + Arguments: + - predicate: A function that takes a list element and returns a boolean + value that says whether that value satisfies the conditions of the + function. + A predicate is a function that takes a list element and returns a Boolean value. @@ -84,6 +104,11 @@ type List ## Checks whether a predicate holds for all elements in this list. + Arguments: + - predicate: A function that takes a list element and returns a boolean + value that says whether that value satisfies the conditions of the + function. + > Example Check if all elements in the list are less than zero. (Cons 1 (Cons 2 Nil)).all (< 0) @@ -92,6 +117,9 @@ type List ## Checks whether this list contains a given value as an element. + Arguments: + - elem: The element to check if it is in the list. + > Example Checking if the list contains the number 72. (Cons 1 (Cons 72 Nil)).contains 72 @@ -118,9 +146,14 @@ type List ## Selects all elements of this list which satisfy a predicate. + Arguments: + - predicate: A function that takes a list element and returns a boolean + value that says whether that value satisfies the conditions of the + function. + > Example Selecting all elements that are greater than 3. - (Cons 1 Nil).filter (> 3) + (Cons 1 Nil).filter (> 3) filter : (Any -> Boolean) -> List filter predicate = case this of @@ -132,11 +165,12 @@ type List ## Applies a function to each element of the list, returning the list of results. + Arguments: + - f: The function to apply to each element of the list. + > Example - In the following example, we add `1` to each element of the list: + Add `1` to each element of the list: (Cons 0 <| Cons 1 <| Cons 2 <| Nil) . map +1 - The result of running the code above is: - Cons 1 <| Cons 2 <| Cons 3 <| Nil map : (Any -> Any) -> List map f = case this of Nil -> Nil @@ -147,12 +181,14 @@ type List ## Applies a function to each element of the list. + Arguments: + - f: The function to apply to each element of the list. + Unlike `map`, this method does not return the individual results, therefore it is only useful for side-effecting computations. > Example - In the following example, we're printing each element of the list - to the standard output: + Print each of the list elements to the standard output. (Cons 0 <| Cons 1 <| Cons 2 <| Nil) . each IO.println each : (Any -> Any) -> Nothing each f = @@ -176,6 +212,9 @@ type List ## Creates a new list with the first `count` elements at the start of `this` removed. + Arguments: + - count: The number of elements to take drop the start of `this`. + > Example Removing the first element from a list. (Cons 1 (Cons 2 (Nil))).drop_start 1 @@ -187,6 +226,9 @@ type List ## Creates a new list consisting of the first `count` elements at the start of `this`. + Arguments: + - count: The number of elements to take from the start of `this`. + > Example Obtaining the first 2 elements of a list. (Cons 1 (Cons 2 (Cons 3 Nil))).take_start 2 diff --git a/distribution/std-lib/Standard/src/Base/Data/Locale.enso b/distribution/std-lib/Standard/src/Base/Data/Locale.enso index da3c918be1..f25cff0a5b 100644 --- a/distribution/std-lib/Standard/src/Base/Data/Locale.enso +++ b/distribution/std-lib/Standard/src/Base/Data/Locale.enso @@ -15,89 +15,171 @@ default : Locale default = here.from_java JavaLocale.ROOT ## A locale representing Bangladesh. + + > Example + Get the Bangladeshi locale. + Locale.bangladesh bangladesh : Locale bangladesh = here.from_language_tag "bn-BD" ## A locale representing Brazil. + + > Example + Get the Brazilian locale. + Locale.brazil brazil : Locale brazil = here.from_language_tag "pt-BR" ## A locale representing Canada with language English. + + > Example + Get the Canadian english locale. + Locale.canada_english canada_english : Locale canada_english = here.from_language_tag "en-CA" ## A locale representing Canada with language French. + + > Example + Get the Canadian french locale. + Locale.canada_french canada_french : Locale canada_french = here.from_language_tag "fr-CA" ## A locale representing the PRC. + + > Example + Get the PRC locale. + Locale.china china : Locale china = here.from_language_tag "zh-CN" ## A locale representing France. + + > Example + Get the French locale. + Locale.france france : Locale france = here.from_language_tag "fr-FR" ## A locale representing Germany. + + > Example + Get the German locale. + Locale.germany germany : Locale germany = here.from_language_tag "de-DE" ## A locale representing India with language Hindi. + + > Example + Get the Indian hindi locale. + Locale.india_hindi india_hindi : Locale india_hindi = here.from_language_tag "hi-IN" ## A locale representing India with language English. + + > Example + Get the Indian english locale. + Locale.indian_english india_english : Locale india_english = here.from_language_tag "en-IN" ## A locale representing Indonesia. + + > Example + Get the Indonesian locale. + Locale.indonesia indonesia : Locale indonesia = here.from_language_tag "id-ID" ## A locale representing Italy. + + > Example + Get the Italian locale. + Locale.italy italy : Locale italy = here.from_language_tag "it-IT" ## A locale representing Japan. + + > Example + Get the Japanese locale. + Locale.japan japan : Locale japan = here.from_language_tag "jp-JP" ## A locale representing Mexico. + + > Example + Get the Mexican locale. + Locale.mexico mexico : Locale mexico = here.from_language_tag "es-MX" ## A locale representing Nigeria. + + > Example + Get the Nigerian locale. + Locale.nigeria nigeria : Locale nigeria = here.from_language_tag "en-NG" ## A locale representing paksitan with language Urdu. + + > Example + Get the Pakistani urdu locale. + Locale.pakistan_urdu pakistan_urdu : Locale pakistan_urdu = here.from_language_tag "ur-PK" ## A locale representing paksitan with language English. + + > Example + Get the Pakistani english locale. + Locale.bangladesh pakistan_english : Locale pakistan_english = here.from_language_tag "en-PK" ## A locale representing Russia. + + > Example + Get the Russian locale. + Locale.russia russia : Locale russia = here.from_language_tag "ru-RU" ## A locale representing South Korea. + + > Example + Get the South Korean locale. + Locale.south_korea south_korea : Locale south_korea = here.from_language_tag "ko-KR" ## A locale representing the UK. + + > Example + Get the british locale. + Locale.uk uk : Locale uk = here.from_language_tag "en-GB" ## A locale representing the United States. + + > Example + Get the US locale. + Locale.us us : Locale us = here.from_language_tag "en-US" ## Construct a new locale. - In addition to the basic constructors, it can take a vector containing locale - properties. + Arguments: + - language: The language tag for the locale. + - country: The country tag for the locale. + - variant: The variant for the locale. > Example A locale representing en-GB.UTF-8. @@ -111,27 +193,28 @@ new language country=Nothing variant=Nothing = ## Returns the locale specified by the provided IETF BCP47 language tag string. - If the specified language tag contains any ill-formed subtags, the first such - subtag and all following subtags are ignored. + ? Language Tag Syntax + If the specified language tag contains any ill-formed subtags, the first + such subtag and all following subtags are ignored. - The following conversions are performed: - - The language code "und" is mapped to language "". - - The language codes "he", "yi", and "id" are mapped to "iw", "ji", and "in" - respectively. - - The portion of a private use subtag prefixed by "lvariant", if any, is - removed and appended to the variant field in the result locale (without - case normalization). - - When the languageTag argument contains an extlang subtag, the first such - subtag is used as the language, and the primary language subtag and other - extlang subtags are ignored. - - Case is normalized except for variant tags, which are left unchanged. - Language is normalized to lower case, script to title case, country to - upper case, and extensions to lower case. - - If, after processing, the locale would exactly match either ja_JP_JP or - th_TH_TH with no extensions, the appropriate extensions are added. + The following conversions are performed: + - The language code "und" is mapped to language "". + - The language codes "he", "yi", and "id" are mapped to "iw", "ji", and + "in" respectively. + - The portion of a private use subtag prefixed by "lvariant", if any, is + removed and appended to the variant field in the result locale (without + case normalization). + - When the languageTag argument contains an extlang subtag, the first such + subtag is used as the language, and the primary language subtag and other + extlang subtags are ignored. + - Case is normalized except for variant tags, which are left unchanged. + Language is normalized to lower case, script to title case, country to + upper case, and extensions to lower case. + - If, after processing, the locale would exactly match either ja_JP_JP or + th_TH_TH with no extensions, the appropriate extensions are added. - This implements the 'Language-Tag' production of BCP47, and so supports - grandfathered (regular and irregular) as well as private use language tags. + This implements the 'Language-Tag' production of BCP47, and so supports + grandfathered (regular and irregular) as well as private use language tags. > Example Creating the locale en_US. @@ -148,21 +231,38 @@ from_language_tag tag = - A country code, which is optional. - A variant, which is optional. type Locale + + ## A type representing a locale. + + Arguments: + - java_locale: The Java locale representation used internally. type Locale java_locale ## Gets the language from the locale. + + > Example + Get the language tag from the default locale. + Locale.default.language language : Text | Nothing language = lang = this.java_locale.getLanguage if lang.is_empty then Nothing else lang ## Gets the country from the locale. + + > Example + Get the country tag from the default locale. + Locale.default.country country : Text | Nothing country = place = this.java_locale.getCountry if place.is_empty then Nothing else place - ## Gets the country from the locale. + ## Gets the variant from the locale. + + > Example + Get the variant tag from the default locale. + Locale.default.variant variant : Text | Nothing variant = var = this.java_locale.getVariant @@ -170,6 +270,10 @@ type Locale ## Gets a representation of the language in the locale that can be shown to the user. + + > Example + Get the display language tag from the default locale. + Locale.default.display_language display_language : Text | Nothing display_language = disp = this.java_locale.getDisplayLanguage @@ -177,6 +281,10 @@ type Locale ## Gets a representation of the country in the locale that can be shown to the user. + + > Example + Get the display country tag from the default locale. + Locale.default.display_country display_country : Text | Nothing display_country = disp = this.java_locale.getDisplayCountry @@ -184,16 +292,28 @@ type Locale ## Gets a representation of the variant in the locale that can be shown to the user. + + > Example + Get the display variant tag from the default locale. + Locale.default.display_variant display_variant : Text | Nothing display_variant = disp = this.java_locale.getDisplayVariant if disp.is_empty then Nothing else disp ## Converts the locale to text. + + > Example + Convert the default locale to text. + Locale.default.to_text to_text : Text | Nothing to_text = this.java_locale.toLanguageTag ## A Locale to Json conversion + + > Example + Convert the default locale to JSON. + Locale.default.to_json to_json : Json.Object to_json = b = Vector.new_builder @@ -204,6 +324,11 @@ type Locale Json.from_pairs b.to_vector ## PRIVATE + + Convert a java locale to an Enso locale. + + Arguments: + - java: The java locale value. from_java : JavaLocale -> Locale from_java java = Locale java diff --git a/distribution/std-lib/Standard/src/Base/Data/Map.enso b/distribution/std-lib/Standard/src/Base/Data/Map.enso index ee0ed7e3ef..712b737df5 100644 --- a/distribution/std-lib/Standard/src/Base/Data/Map.enso +++ b/distribution/std-lib/Standard/src/Base/Data/Map.enso @@ -2,19 +2,39 @@ from Standard.Base import all import Standard.Base.Data.Map.Internal -## An error for getting a missing value from a map. +## UNSTABLE + + An error for getting a missing value from a map. + + Arguments: + - key: The key that was asked for. type No_Value_For_Key key ## Returns an empty map. + + > Example + Create an empty map. + Map.empty empty : Map empty = Tip ## Returns a single-element map with the given key and value present. + + Arguments: + - key: The key to update in the map. + - value: The value to store against 'key' in the map. + + > Example + Create a single element map storing the key 1 and the value 2. + Map.singleton 1 2 singleton : Any -> Any -> Map singleton key value = Bin 1 key value Tip Tip ## Builds a map from a vector of key-value pairs. + Arguments: + - vec: A vector of key-value pairs. + > Example Building a map containing two key-value pairs. Map.from_vector [[1, 2], [3, 4]] @@ -24,27 +44,59 @@ from_vector vec = vec.fold Map.empty (m -> el -> m.insert (el.at 0) (el.at 1)) ## A key-value store. This type assumes all keys are pairwise comparable, using the `<`, `>` and `==` operators. type Map + + ## PRIVATE + A key-value store. This type assumes all keys are pairwise comparable, + using the `<`, `>` and `==` operators. type Tip + + ## PRIVATE + A key-value store. This type assumes all keys are pairwise comparable, + using the `<`, `>` and `==` operators. + + Arguments: + - s: The size of the tree at this node. + - key: The key stored at this node. + - value: The value stored at this node. + - left: The left subtree. + - right: The right subtree. type Bin s key value left right ## Checks if the map is empty. + + > Example + Check if a singleton map is empty. + Map.singleton 1 2 . is_empty is_empty : Boolean is_empty = case this of Bin _ _ _ _ _ -> False Tip -> True ## Checks if the map is not empty. + + > Example + Check if a singleton map is not empty. + Map.singleton 1 2 . not_empty not_empty : Boolean not_empty = this.is_empty.not ## Returns the number of entries in this map. + + > Example + Get the size of a singleton map. + Map.singleton 1 2 . size size : Integer size = case this of Bin s _ _ _ _ -> s Tip -> 0 ## Converts the map into a vector of `[key, value]` pairs. + The returned vector is sorted in the increasing order of keys. + + > Example + Convert a singleton map to a vector. + Map.singleton 1 2 . to_vector to_vector : Vector.Vector to_vector = builder = Vector.new_builder @@ -60,23 +112,49 @@ type Map result ## Returns a text representation of this map. + + > Example + Convert an empty map to text. + Map.empty.to_text to_text : Text to_text = this.to_vector.to_text ## Checks if this map is equal to another map. + Arguments: + - that: The map to compare `this` to. + Maps are equal when they contained the same keys and the values associated with each key are pairwise equal. + + > Example + Checking two singleton maps for equality. + (Map.singleton 1 2) == (Map.singleton 2 3) == : Map -> Boolean == that = this.to_vector == that.to_vector - ## Inserts a key-value mapping into this map. If `key` is already present, - it will be overriden with the new `value`. + ## Inserts a key-value mapping into this map, overriding any existing + instance of `key` with the new `value`. + + Arguments: + - key: The key to insert the value for. + - value: The value to associate with `key`. + + > Example + Insert the value 3 into a map for the key 1. + Map.empty.insert 1 3 insert : Any -> Any -> Map insert key value = Internal.insert this key value - ## Gets the value associated with `key` in this map, or returns a - `Nothing`, if `key` is not present. + ## Gets the value associated with `key` in this map, or throws a `Nothing`, + if `key` is not present. + + Arguments: + - key: The key to look up in the map. + + > Example + Get the value for the key 2 in a map. + Map.empty.get 2 get : Any -> Any ! Nothing get key = go map = case map of @@ -89,12 +167,25 @@ type Map ## Gets the value associated with `key` in this map, or returns `other` if it isn't present. + + Arguments: + - key: The key to look up in the map. + - other: The value to use if the key isn't present. + + > Example + Get the value for the key 2 in a map or instead return 10 if it isn't + present. + Map.empty.get_or_else 2 10 get_or_else : Any -> Any -> Any get_or_else key ~other = this.get key . catch (_ -> other) ## Transforms the map's keys and values to create a new map. + Arguments: + - function: The function used to transform the map, taking a key and a + value and returning a pair of `[key, value]`. + > Example Turn all keys into `Text` and double the values for a map `m`. m.transform (k -> v -> [k.to_text, v*2]) @@ -106,6 +197,10 @@ type Map ## Maps a function over each value in this map. + Arguments: + - function: The function to apply to each value in the map, taking a + value and returning a value. + > Example Turn all values into `Text` for a map `m`. m.map (v -> v.to_text) @@ -117,6 +212,10 @@ type Map ## Maps a function over each key-value pair in the map, transforming the value. + Arguments: + - function: The function to apply to each key and value in the map, + taking a key and a value and returning a value. + > Example Adding the key to the value in a map `m`. m.map_with_key (k -> v -> k + v) @@ -130,6 +229,10 @@ type Map ## Maps a function over each key in this map. + Arguments: + - function: The function to apply to each key in the map, taking a key + and returning a key. + > Example Doubling all keys in the map `m`. m.map_keys (k -> k*2) @@ -140,6 +243,10 @@ type Map ## Applies a function to each value in the map. + Arguments: + - function: The function to apply to each value in the map, taking a + value and returning anything. + This method does not return the results, so is only useful for performing computations with side-effects. @@ -153,6 +260,10 @@ type Map ## Applies a function to each key-value pair in the map. + Arguments: + - function: The function to apply to each key-value pair in the map, + taking a key and a value and returning anything. + This method does not return the results, so is only useful for performing computations with side-effects. @@ -172,6 +283,10 @@ type Map ## Combines the values in the map. + Arguments: + - init: The initial value for the fold. + - function: A binary function to apply to pairs of values in the map. + > Example Summing all of the values in the map `m`. m.fold 0 (+) @@ -187,6 +302,11 @@ type Map ## Combines the key-value pairs in the map. + Arguments: + - init: The initial value for the fold. + - function: A function taking the left value, the current key, and the + current value, and combining them to yield a single value. + > Example Sum the keys and values in the map `m`. m.fold_with_key 0 (l -> k -> v -> l + k + v) diff --git a/distribution/std-lib/Standard/src/Base/Data/Map/Internal.enso b/distribution/std-lib/Standard/src/Base/Data/Map/Internal.enso index aa666b9b93..fdffb15c2c 100644 --- a/distribution/std-lib/Standard/src/Base/Data/Map/Internal.enso +++ b/distribution/std-lib/Standard/src/Base/Data/Map/Internal.enso @@ -4,14 +4,32 @@ from Standard.Base.Data.Map import all ## PRIVATE - Helper used in the insert operation. + A helper used in the insert operation to insert into the left subtree. + + Arguments: + - key: The key to insert. + - value: The value to insert. + - k: The previous top key of the left subtree. + - v: The previous top value of the left subtree. + - l: The left subtree. + - r: The right subtree. +insert_l : Any -> Any -> Any -> Any -> Tree -> Tree -> Tree insert_l key value k v l r = new_left = here.insert l key value here.balance_left k v new_left r ## PRIVATE - Helper used in the insert operation. + A helper used in the insert operation to insert into the right subtree. + + Arguments: + - key: The key to insert. + - value: The value to insert. + - k: The previous top key of the right subtree. + - v: The previous top value of the right subtree. + - l: The left subtree. + - r: The right subtree. +insert_r : Any -> Any -> Any -> Any -> Tree -> Tree -> Tree insert_r key value k v l r = new_right = here.insert r key value here.balance_right k v l new_right @@ -20,10 +38,15 @@ insert_r key value k v l r = Helper for inserting a new key-value pair into a map. + Arguments: + - map: The map into which the insertion is performed. + - key: The key for which to insert the value into the map. + - value: The value to insert into the map at the given key. + The algorithm used here is based on the paper "Implementing Sets Efficiently - in a Functional Language" by Stephen Adams. - Implementation is based on Haskell's `Data.Map.Strict` implemented in the - `containers` package. + in a Functional Language" by Stephen Adams. The implementation is based on + Haskell's `Data.Map.Strict` as implemented in the `containers` package. +insert : Map -> Any -> Any -> Map insert map key value = case map of Bin s k v l r -> if key > k then @Tail_Call here.insert_r key value k v l r else @@ -34,6 +57,13 @@ insert map key value = case map of ## PRIVATE Rebalances the map after the left subtree grows. + + Arguments: + - k: The old top key of the left subtree. + - x: The old top value of the left subtree. + - l: The left subtree. + - r: The right subtree. +balance_left : Any -> Any -> Tree -> Tree -> Tree balance_left k x l r = case r of Bin rs _ _ _ _ -> case l of Bin ls lk lx ll lr -> @@ -62,6 +92,12 @@ balance_left k x l r = case r of ## PRIVATE Rebalances the map after the right subtree grows. + + Arguments: + - k: The old top key of the right subtree. + - x: The old top value of the right subtree. + - l: The left subtree. + - r: The right subtree. balance_right k x l r = case l of Bin ls _ _ _ _ -> case r of Bin rs rk rx rl rr -> @@ -109,6 +145,10 @@ delta = 3 ## PRIVATE Gets the size of a map. + + Arguments: + - m: The map to get the size of. +size: Map -> Integer size m = case m of Bin s _ _ _ _ -> s _ -> 0 diff --git a/distribution/std-lib/Standard/src/Base/Data/Maybe.enso b/distribution/std-lib/Standard/src/Base/Data/Maybe.enso index fc22f821dd..19cd060e6b 100644 --- a/distribution/std-lib/Standard/src/Base/Data/Maybe.enso +++ b/distribution/std-lib/Standard/src/Base/Data/Maybe.enso @@ -7,6 +7,9 @@ type Maybe Nothing ## A value. + + Arguments: + - value: The contained value in the maybe. type Some value ## Applies the provided function to the contained value if it exists, diff --git a/distribution/std-lib/Standard/src/Base/Data/Noise.enso b/distribution/std-lib/Standard/src/Base/Data/Noise.enso index bcc25177dc..83afd0be7e 100644 --- a/distribution/std-lib/Standard/src/Base/Data/Noise.enso +++ b/distribution/std-lib/Standard/src/Base/Data/Noise.enso @@ -4,6 +4,10 @@ from Standard.Base.Data.Noise.Generator import all ## Generate noise based on the input number. + Arguments: + - interval: An interval in which the noise should be generated. + - gen: The generator to use for generating noise. + The output of the noise generator will depend on the input and the range over which the noise is being generated. diff --git a/distribution/std-lib/Standard/src/Base/Data/Noise/Generator.enso b/distribution/std-lib/Standard/src/Base/Data/Noise/Generator.enso index 74b9070dfa..958e9135f4 100644 --- a/distribution/std-lib/Standard/src/Base/Data/Noise/Generator.enso +++ b/distribution/std-lib/Standard/src/Base/Data/Noise/Generator.enso @@ -6,16 +6,24 @@ import Standard.Base.Error.Extensions polyglot java import java.lang.Long polyglot java import java.util.Random -## The interface for the noise generator abstraction. +## PRIVATE + + The interface for the noise generator abstraction. To be a valid generator, it must provide the `step` method as described below. type Generator + + ## PRIVATE + + The basic generator type. type Generator - ## Step the generator to produce the next value.. + ## PRIVATE - The parameters are as follows: + Step the generator to produce the next value.. + + Arguments: - The input number, which is intended for use as a seed. - A range for output values, which should range over the chosen output type. @@ -31,9 +39,23 @@ type Generator It produces what is commonly termed "white" noise, where any value in the range has an equal chance of occurring. type Deterministic_Random + + ## A determinstic random noise generator that performs a peterbation of the + input + + It produices what is commonly termed as "white" noise, where any value in + the range has an equal chance of occurring. type Deterministic_Random ## Step the generator to produce the next value. + + Arguments: + - input: The seed number to perturb. + - interval: The interval over which the noise should be generated. + + > Example + Step the generator with the input 1 and range 0 to 1 + Deterministic_Random.step 1 (Interval.inclusive 0 1) step : Number -> Interval -> Number step input interval = max_long = Long.MAX_VALUE diff --git a/distribution/std-lib/Standard/src/Base/Data/Number/Extensions.enso b/distribution/std-lib/Standard/src/Base/Data/Number/Extensions.enso index 2dc457d842..58ded10aef 100644 --- a/distribution/std-lib/Standard/src/Base/Data/Number/Extensions.enso +++ b/distribution/std-lib/Standard/src/Base/Data/Number/Extensions.enso @@ -7,99 +7,209 @@ polyglot java import java.lang.String ## Computes the inverse of the sine function Selects a value in the -pi/2 through pi/2 range. + + > Example + Calculate the inverse sine of 1. + 1.asin Number.asin : Decimal Number.asin = Math.asin this.to_decimal ## Computes the inverse of the cosine function. Selects a value in the -pi/2 through pi/2 range. + + > Example + Calculate the inverse cosine of 1. + 1.acos Number.acos : Decimal Number.acos = Math.acos this.to_decimal ## Computes the inverse of the tangent function. Selects a value in the -pi/2 through pi/2 range. + + > Example + Calculate the inverse tangent of 1. + 1.acos Number.atan : Decimal Number.atan = Math.atan this.to_decimal ## Computes the argument (angle) in the conversion from cartesian - to polar coordinates. + to polar coordinates, taking `this` as the x coordinate. + + Arguments: + - y: The y coordinate. The returned angle is in the -pi through pi range. + + > Example + Convert the coordinates 1 and 2 to polar form. + 1.atan_2 2 Number.atan_2 : Number -> Decimal Number.atan_2 y = Math.atan2 this.to_decimal y.to_decimal ## Computes the sine function. + + > Example + Calculate the sine of 2. + 2.sin Number.sin : Decimal Number.sin = Math.sin this.to_decimal ## Computes the cosine function. + + > Example + Calculate the cosine of 2. + 2.cos Number.cos : Decimal Number.cos = Math.cos this.to_decimal ## Computes the tangent function. + + > Example + Calculate the tangent of 2. + 2.tan Number.tan : Decimal Number.tan = Math.tan this.to_decimal ## Computes the hyperbolic sine function. + + > Example + Calculate the hyperbolic sine of 1. + 1.sinh Number.sinh : Decimal Number.sinh = Math.sinh this.to_decimal ## Computes the hyperbolic cosine function. + + > Example + Calcualte the hyperbolic cosine of 1. + 1.cosh Number.cosh : Decimal Number.cosh = Math.cosh this.to_decimal ## Computes the hyperbolic tangent function. + + > Example + Calculate the hyperbolic tangent of 1. + 1.tanh Number.tanh : Decimal Number.tanh = Math.tanh this.to_decimal -## Computes the exponential function. +## Computes the exponential function, raising Euler's number `r` to the power of + `this`. + + > Example + Calculate e to the 4th power. + 4.exp Number.exp : Decimal Number.exp = Math.exp this.to_decimal ## Computes the natural logarithm function. + + > Example + Calculate the natural logarithm of 2. + 2.ln Number.ln : Decimal Number.ln = Math.log this.to_decimal ## Computes the square root of `this`. + + > Example + Calculate the square root of 8. + 8.sqrt Number.sqrt : Decimal Number.sqrt = Math.sqrt this.to_decimal ## Computes the `base`-log of `this`. + + Arguments: + - base: The base for the logarithm. + + > Example + Calculate log 2 of 4. + 4.log 2 Number.log : Number -> Decimal Number.log base = this.ln / base.ln -# TODO this should expose a more-user friendly API in the future. -## Converts a decimal value to a string, using the Java string formatting +## UNSTABLE The API will become more user-friendly in future. + + Converts a decimal value to a string, using the Java string formatting syntax. + + Arguments: + - fmt: The java-style formatting specifier. + + > Example + Convert the value 5 to a string. + 5.fmt "%d" Decimal.format : Text -> Text Decimal.format fmt = String.format fmt this ## Creates a new right-exclusive range of integers from `this` to `n`. + + Arguments: + - n: The end of the range. + + > Example + Create a range from 1 to 5. + 1.up_to 5 Integer.up_to : Integer -> Range Integer.up_to n = Range this n ## Checks equality of numbers, using an `epsilon` value. - Returns `True` when `this` and `that` are at most `epsilon` apart. + Arguments: + - that: The number to check equality against. + - epsilon: The value by which `this` and `that` can be separated by before + counting as not equal. + + > Example + Check if 1 is equal to 1.0000001 within 0.001. + 1.equals 1.0000001 epsilon=0.001 Number.equals : Number -> Number -> Boolean Number.equals that epsilon=0.0 = (this - that).abs <= epsilon ## Returns the smaller value of `this` and `that`. + + Arguments: + - that: The number to compare `this` against. + + > Example + Find the minimum of 2 and 5. + 2.min 5 Number.min : Number -> Number Number.min that = if this < that then this else that ## Returns the larger value of `this` and `that`. + + Arguments: + - that: The number to compare `this` against. + + > Example + Find the maximum of 2 and 5. + 2.max 5 Number.max : Number -> Number Number.max that = if this > that then this else that ## Number to JSON conversion. + + > Example + Convert the number 8 to JSON. + 8.to_json Number.to_json : Json.Number Number.to_json = Json.Number this -## Parses a textual representation of a decimal into a decimal number. - Returns `Nothing` if the text does not represent a valid decimal. -Decimal.parse : Text -> Decimal | Nothing -Decimal.parse text = - Panic.recover (Double.parseDouble text) . catch (_ -> Nothing) +## Parses a textual representation of a decimal into a decimal number, returning + `Nothing` if the text does not represent a valid decimal. + + Arguments: + - text: The text to parse into a decimal. + + > Example + Parse the text "7.6" into a decimal number. + Decimal.parse 7.6 +Decimal.parse : Text -> Decimal ! Nothing +Decimal.parse text = + Panic.recover (Double.parseDouble text) . catch (_ -> Error.throw Nothing) diff --git a/distribution/std-lib/Standard/src/Base/Data/Ordering.enso b/distribution/std-lib/Standard/src/Base/Data/Ordering.enso index 895d34ec95..d1067be403 100644 --- a/distribution/std-lib/Standard/src/Base/Data/Ordering.enso +++ b/distribution/std-lib/Standard/src/Base/Data/Ordering.enso @@ -12,14 +12,15 @@ from Builtins export Less, Equal, Greater The result should be returned in terms of how `this` orders in comparison to `that`. So, if `this` is greater than `that`, you should return `Greater.` type Ordering - ## An ordering where a compared value is less than another. Less - ## An ordering where a compared value is equal to another. Equal - ## An ordering where a compared value is greater than another. Greater ## Converts the ordering to the signed notion of ordering based on integers. + + > Example + Converting equal ordering to a signed number. + Ordering.Equal.to_sign to_sign : Integer to_sign = case this of Less -> -1 diff --git a/distribution/std-lib/Standard/src/Base/Data/Ordering/Sort_Order.enso b/distribution/std-lib/Standard/src/Base/Data/Ordering/Sort_Order.enso index 3f4461a56e..63eb08ef5d 100644 --- a/distribution/std-lib/Standard/src/Base/Data/Ordering/Sort_Order.enso +++ b/distribution/std-lib/Standard/src/Base/Data/Ordering/Sort_Order.enso @@ -2,8 +2,10 @@ from Standard.Base import all ## A descriptor for a sort ordering. type Sort_Order + ## Elements should be sorted in ascending order. type Ascending + ## Elements should be sorted in descending order. type Descending diff --git a/distribution/std-lib/Standard/src/Base/Data/Pair.enso b/distribution/std-lib/Standard/src/Base/Data/Pair.enso index 351eb6fdc7..5167372cc3 100644 --- a/distribution/std-lib/Standard/src/Base/Data/Pair.enso +++ b/distribution/std-lib/Standard/src/Base/Data/Pair.enso @@ -2,4 +2,12 @@ from Standard.Base import all ## A pair of elements. type Pair + + ## UNSTABLE + + A simple pair of elements. + + Arguments: + - first: The first element. + - second: The second element. type Pair first second diff --git a/distribution/std-lib/Standard/src/Base/Data/Range.enso b/distribution/std-lib/Standard/src/Base/Data/Range.enso index 1aff9fd50f..b0119aba0c 100644 --- a/distribution/std-lib/Standard/src/Base/Data/Range.enso +++ b/distribution/std-lib/Standard/src/Base/Data/Range.enso @@ -2,6 +2,13 @@ from Standard.Base import all ## Represents a right-exclusive range of integer values. type Range + + ## UNSTABLE + A representation of a right-exclusive range of integer values. + + Arguments: + - start: The left boundary of the range. Its value is included. + - end: The right boundary of the range. Its value is excluded. type Range start end ## Get the number of elements in the range. @@ -30,6 +37,9 @@ type Range ## Applies a function for each element in the range. + Arguments: + - function: The function to apply to each integer in the range. + > Example To print all the numbers from 1 to 100 use: 1.up_to 101 . each IO.println @@ -44,6 +54,11 @@ type Range ## Combines all the elements of the range, by iteratively applying the passed function with next elements of the range. + Arguments: + - init: The initial integral value for the fold. + - function: A binary function taking an item and a number, and returning + an item. + In general, the result of Range start end . fold init f is the same as @@ -53,18 +68,20 @@ type Range In the following example, we'll compute the sum of all elements of a range: Range 0 100 . fold 0 (+) - fold : Any -> (Number -> Any) -> Any - fold initial function = + fold : Any -> (Any -> Number -> Any) -> Any + fold init function = it acc start end = if start == end then acc else new_acc = function acc start @Tail_Call it new_acc start+1 end - res = it initial this.start this.end + res = it init this.start this.end res ## Checks whether `predicate` is satisfied for all numbers in this range. - A predicate is a function that takes an element in the range and returns - a boolean. + Arguments: + - predicate: A function that takes a list element and returns a boolean + value that says whether that value satisfies the conditions of the + function. > Example Checking that all numbers in the range are greater than 5. @@ -79,8 +96,10 @@ type Range ## Checks whether `predicate` is satisfied for any number in this range. - A predicate is a function that takes an element in the range and returns - a boolean. + Arguments: + - predicate: A function that takes a list element and returns a boolean + value that says whether that value satisfies the conditions of the + function. > Example Checking that at least one number in the range is greater than 10. @@ -94,8 +113,10 @@ type Range ## Checks whether `predicate` is satisfied for any number in this range. - A predicate is a function that takes an element in the range and returns - a boolean. + Arguments: + - predicate: A function that takes a list element and returns a boolean + value that says whether that value satisfies the conditions of the + function. > Example Checking that at least one number in the range is greater than 10. diff --git a/distribution/std-lib/Standard/src/Base/Data/Text/Extensions.enso b/distribution/std-lib/Standard/src/Base/Data/Text/Extensions.enso index 40fa26a263..5b2a57ae0f 100644 --- a/distribution/std-lib/Standard/src/Base/Data/Text/Extensions.enso +++ b/distribution/std-lib/Standard/src/Base/Data/Text/Extensions.enso @@ -13,11 +13,14 @@ polyglot java import org.enso.base.Text_Utils ## Computes the number of characters in the text. - A character is defined as an Extended Grapheme Cluster, see - Unicode Standard Annex 29. + ! What is a Character? + A character is defined as an Extended Grapheme Cluster, see Unicode + Standard Annex 29. This is the smallest unit that still has semantic + meaning in most text-processing applications. - This is the smallest unit that still has semantic meaning in most - text-processing applications. + > Example + Getting the length of the string "건반(Korean)". + "건반(Korean)".length Text.length : Integer Text.length = iterator = BreakIterator.getCharacterInstance @@ -30,13 +33,19 @@ Text.length = @Tail_Call count counter next_nxt count 0 nxt -## Applies `function` to each character in `this`. +## Applies the provided `function` to each character in `this`. - A character is defined as an Extended Grapheme Cluster, see - Unicode Standard Annex 29. + Arguments: + - function: The operation to apply to each character in the text. - This is the smallest unit that still has semantic meaning in most - text-processing applications. + ! What is a Character? + A character is defined as an Extended Grapheme Cluster, see Unicode + Standard Annex 29. This is the smallest unit that still has semantic + meaning in most text-processing applications. + + > Example + Print each character in the text "aaa". + "aaa".each IO.println Text.each : (Text -> Any) -> Nothing Text.each function = iterator = BreakIterator.getCharacterInstance @@ -54,11 +63,14 @@ Text.each function = ## Returns a vector containing all characters in the given text. - A character is defined as an Extended Grapheme Cluster, see - Unicode Standard Annex 29. + ! What is a Character? + A character is defined as an Extended Grapheme Cluster, see Unicode + Standard Annex 29. This is the smallest unit that still has semantic + meaning in most text-processing applications. - This is the smallest unit that still has semantic meaning in most - text-processing applications. + > Example + Get the individual characters in the text "건반(Korean)". + "건반(Korean)".characters Text.characters : Vector.Vector Text.characters = bldr = Vector.new_builder @@ -68,12 +80,16 @@ Text.characters = ## Takes a separator string and returns a vector resulting from splitting `this` on each occurence of `separator`. + Arguments: + - separator: The separator to use to split the text. + > Example - In the following example, we'll split the text into a vector of - comma-separated items: + Split the comma-separated text into a vector of items. "ham,eggs,cheese,tomatoes".split "," - The code above returns: - ["ham", "eggs", "cheese", "tomatoes"] + + > Example + Split the string on whitespace into a vector of items. + "ham eggs cheese tomatoes".split Split_Kind.Whitespace Text.split : Split_Kind -> Vector.Vector Text.split (separator = Split_Kind.Whitespace) = result = case separator of @@ -85,12 +101,15 @@ Text.split (separator = Split_Kind.Whitespace) = ## Returns a vector containing all words in the given text. - A word is defined based on the definition of Word Boundaries in the Unicode - Standard Annex 29, supplemented by language-specific dictionaries for - Chinese, Japanese, Thai, and Khmer. + Arguments: + - keep_whitespace: Whether or not the whitespace around the words should be + preserved. If set to `True`, the whitespace will be included as a "word" in + the output. - By default, the function doesn't include the whitespace between words, but - this can be enabled. + ! What is a Word? + A word is defined based on the definition of Word Boundaries in the Unicode + Standard Annex 29, supplemented by language-specific dictionaries for + Chinese, Japanese, Thai, and Khmer. > Example Getting the words in the sentence "I have not one, but two cats." @@ -119,44 +138,53 @@ Text.words keep_whitespace=False = ## Checks whether `this` is equal to `that`. - The definition of equality includes Unicode canonicalization. I.e. two texts - are equal if they are identical after canonical decomposition. This ensures - that different ways of expressing the same character in the underlying - binary representation are considered equal. + Arguments: + - that: The text to compare `this` for equality with. + + ! Unicode Equality + The definition of equality includes Unicode canonicalization. I.e. two + texts are equal if they are identical after canonical decomposition. This + ensures that different ways of expressing the same character in the + underlying binary representation are considered equal. > Example - The string 'é' (i.e. the character U+00E9, LATIN SMALL LETTER E WITH - ACUTE) is canonically the same as the string 'e\u0301' (i.e. the letter - `e` followed by U+0301, COMBINING ACUTE ACCENT). Therefore: + The string 'é' (i.e. the character U+00E9, LATIN SMALL LETTER E WITH ACUTE) + is canonically the same as the string 'e\u0301' (i.e. the letter `e` + followed by U+0301, COMBINING ACUTE ACCENT). Therefore: ('é' == 'e\u0301') == True Text.== : Any -> Boolean Text.== that = if Meta.is_same_object this Text then Meta.is_same_object that Text else Text_Utils.equals this that -## Checks whether `this` is equal to `that`, ignoring case considerations. +## Checks whether `this` is equal to `that`, ignoring the case of the texts. + + Arguments: + - that: The text to compare `this` for case-insensitive equality with. Two texts are considered equal ignoring case if they are of the same length and corresponding characters are equal ignoring case. - The definition of equality includes Unicode canonicalization. I.e. two texts - are equal if they are identical after canonical decomposition. This ensures - that different ways of expressing the same character in the underlying - binary representation are considered equal. + ! Unicode Equality + The definition of equality includes Unicode canonicalization. I.e. two + texts are equal if they are identical after canonical decomposition. This + ensures that different ways of expressing the same character in the + underlying binary representation are considered equal. > Example - The string 'É' (i.e. the character U+00C9, LATIN CAPITAL LETTER E WITH ACUTE) is equal ignore case to the string 'é' (i.e. the character U+00E9, LATIN SMALL LETTER E WITH ACUTE), which is canonically the same as the string 'e\u0301' (i.e. the letter `e` followed by U+0301, COMBINING ACUTE ACCENT). Therefore: (('É' . equals_ignore_case 'é') && ('é' == 'e\u0301')) == True - Text.equals_ignore_case : Text -> Boolean Text.equals_ignore_case that = Text_Utils.equals_ignore_case this that ## Compare two texts to discover their ordering. + Arguments: + - that: The text to order `this` with respect to. + > Example Checking how "a" orders in relation to "b". "a".compare_to "b" @@ -165,10 +193,24 @@ Text.compare_to that = if this == that then Ordering.Equal else if Text_Utils.lt this that then Ordering.Less else Ordering.Greater ## Check if `this` is empty. + + ! What is Empty? + Text is considered to be empty when its length is zero. + + > Example + Check if the text "aaa" is empty. + "aaa".is_empty Text.is_empty : Boolean Text.is_empty = this == "" ## Check if `this` is not empty. + + ! What is Not Empty? + Text is considered to be not empty when its length is greater than zero. + + > Example + Check if the text "aaa" is not empty. + "aaa".not_empty Text.not_empty : Boolean Text.not_empty = this.is_empty.not @@ -177,14 +219,24 @@ Text.not_empty = this.is_empty.not This is useful for low-level operations, such as binary data encoding and decoding. + + > Example + Get the UTF-8 bytes of the text "Hello". + "Hello".utf_8 Text.utf_8 : Vector.Vector Text.utf_8 = Vector.from_polyglot_array (Text_Utils.get_bytes this) -## Takes an array of bytes and returns Text resulting from decoding it as - UTF-8. +## Takes a vector of bytes and returns Text resulting from decoding it as UTF-8. + + Arguments: + - bytes: The vector of UTF-8 bytes. This is useful for low-level operations, such as binary data encoding and decoding. + + > Example + Decoding the bytes to get a text. + Text.from_utf_8 [-32, -92, -107, -32, -91, -115, -32, -92, -73, -32, -92, -65] Text.from_utf_8 : Vector.Vector -> Text Text.from_utf_8 bytes = Text_Utils.from_utf_8 bytes.to_array @@ -193,6 +245,10 @@ Text.from_utf_8 bytes = Text_Utils.from_utf_8 bytes.to_array This is useful for low-level operations, such as binary data encoding and decoding. + + > Example + Get the codepoints of the text "Hello". + "Hello".codepoints Text.codepoints : Vector.Vector Text.codepoints = Vector.from_polyglot_array (Text_Utils.get_codepoints this) @@ -202,43 +258,115 @@ Text.codepoints = This is useful for low-level operations, such as binary data encoding and decoding. + + > Example + Converting a vector of codepoints back into a text. + Text.from_codepoints [129318, 127996, 8205, 9794, 65039] Text.from_codepoints : Vector.Vector -> Text Text.from_codepoints codepoints = Text_Utils.from_codepoints codepoints.to_array ## Checks whether `this` starts with `prefix`. + + Arguments: + - prefix: The prefix to see if `this` starts with. + + ! Unicode Equality + The definition of equality includes Unicode canonicalization. I.e. two + texts are equal if they are identical after canonical decomposition. This + ensures that different ways of expressing the same character in the + underlying binary representation are considered equal. + + > Example + See if the text "Hello" starts with the prefix "hi". + "Hello".starts_with "hi" Text.starts_with : Text -> Boolean Text.starts_with prefix = Text_Utils.starts_with this prefix ## Checks whether `this` ends with `suffix`. + + Arguments: + - suffix: The suffix to see if `this` ends with. + + ! Unicode Equality + The definition of equality includes Unicode canonicalization. I.e. two + texts are equal if they are identical after canonical decomposition. This + ensures that different ways of expressing the same character in the + underlying binary representation are considered equal. + + > Example + See if the text "Hello" ends with the suffix "low". + "Hello".ends_with "low" Text.ends_with : Text -> Boolean Text.ends_with suffix = Text_Utils.ends_with this suffix ## Checks whether `this` contains `sequence` as its substring. + + Arguments: + - sequence: The text to see if it is contained in `this`. + + ! Unicode Equality + The definition of equality includes Unicode canonicalization. I.e. two + texts are equal if they are identical after canonical decomposition. This + ensures that different ways of expressing the same character in the + underlying binary representation are considered equal. + + > Example + See if the text "Hello" contains the text "ell". + "Hello".contains "ell" Text.contains : Text -> Boolean Text.contains sequence = Text_Utils.contains this sequence ## Replaces each occurrences of `old_sequence` within `this` with `new_sequence`. + Arguments: + - old_sequence: The text to search for in `this`. + - new_sequence: The text to replace any occurrence of `old_sequence` with. + The replacement from the beginning of the text, as shown in the example below. > Example + Replace letters in the text "aaa". 'aaa'.replace 'aa' 'b' == 'ba' Text.replace : Text -> Text -> Text Text.replace old_sequence new_sequence = Text_Utils.replace this old_sequence new_sequence ## Text to JSON conversion. + + > Example + Convert the text "cześć" to JSON. + "cześć".to_json Text.to_json : Json.String Text.to_json = Json.String this ## Takes a non-negative integer and returns a new text, consisting of `count` concatenated copies of `this`. + + Arguments: + - count: The number of times that the text `this` should be repeated to make + the new text. + + > Example + Repeat the string "ABBA" five times. + "ABBA".repeat 5 Text.repeat : Integer -> Text Text.repeat count = 0.up_to count . fold "" acc-> _-> acc + this -## Creates a new text by removing the first `count` characters of `this`. - If `count` is greater than the number of characters in `this`, an empty text - is returned. +## Creates a new text by removing the first `count` characters of `this`, + returning an empty text if `count` is greater than or equal to the length of + `this`. + + Arguments: + - count: The number of characters to remove from the start of `this`. + + ! What is a Character? + A character is defined as an Extended Grapheme Cluster, see Unicode + Standard Annex 29. This is the smallest unit that still has semantic + meaning in most text-processing applications. + + > Example + Removing the first three characters from the text "ABBA". + "ABBA".drop_first 3 Text.drop_first : Integer -> Text Text.drop_first count = iterator = BreakIterator.getCharacterInstance @@ -247,9 +375,21 @@ Text.drop_first count = boundary = iterator.next count if boundary == -1 then '' else Text_Utils.drop_first this boundary -## Creates a new text by removing the last `count` characters of `this`. - If `count` is greater than the number of characters in `this`, an empty text - is returned. +## Creates a new text by removing the last `count` characters of `this`, + returning an empty text if `count` is greater than or equal to the length of + `this`. + + Arguments: + - count: The number of characters to remove from the end of `this`. + + ! What is a Character? + A character is defined as an Extended Grapheme Cluster, see Unicode + Standard Annex 29. This is the smallest unit that still has semantic + meaning in most text-processing applications. + + > Example + Removing the last three characters from the text "ABBA". + "ABBA".drop_last 3 Text.drop_last : Integer -> Text Text.drop_last count = iterator = BreakIterator.getCharacterInstance @@ -258,9 +398,20 @@ Text.drop_last count = boundary = iterator.next -count if boundary == -1 then '' else Text_Utils.substring this 0 boundary -## Creates a new text by selecting the first `count` characters of `this`. - If `count` is greater than the number of characters in `this`, the whole - `this` is returned. +## Creates a new text by selecting the first `count` characters of `this`, + returning `this` if `count` is greater than or equal to the length of `this`. + + Arguments: + - count: The number of characters to take from the start of `this`. + + ! What is a Character? + A character is defined as an Extended Grapheme Cluster, see Unicode + Standard Annex 29. This is the smallest unit that still has semantic + meaning in most text-processing applications. + + > Example + Make a new text from the first two characters of "boo". + "boo".take_first 2 Text.take_first : Integer -> Text Text.take_first count = iterator = BreakIterator.getCharacterInstance @@ -269,9 +420,20 @@ Text.take_first count = boundary = iterator.next count if boundary == -1 then this else Text_Utils.substring this 0 boundary -## Creates a new text by selecting the last `count` characters of `this`. - If `count` is greater than the number of characters in `this`, the whole - `this` is returned. +## Creates a new text by selecting the last `count` characters of `this`, + returning `this` if `count` is greater than or equal to the length of `this`. + + Arguments: + - count: The number of characters to take from the end of `this`. + + ! What is a Character? + A character is defined as an Extended Grapheme Cluster, see Unicode + Standard Annex 29. This is the smallest unit that still has semantic + meaning in most text-processing applications. + + > Example + Make a new text from the last two characters of "boo". + "boo".take_last 2 Text.take_last : Integer -> Text Text.take_last count = iterator = BreakIterator.getCharacterInstance @@ -283,8 +445,13 @@ Text.take_last count = ## Converts each character in `this` to lower case. Arguments: - - locale: specifies the locale for charater case mapping. Defaults to the - `Locale.default` locale. + - locale: specifies the locale for charater case mapping. Defaults to the + `Locale.default` locale. + + ! What is a Character? + A character is defined as an Extended Grapheme Cluster, see Unicode + Standard Annex 29. This is the smallest unit that still has semantic + meaning in most text-processing applications. > Example Converting a text to lower case in the default locale: @@ -300,8 +467,13 @@ Text.to_lower_case locale=Locale.default = ## Converts each character in `this` to upper case. Arguments: - - locale: specifies the locale for charater case mapping. Defaults to - `Locale.default`. + - locale: specifies the locale for charater case mapping. Defaults to + `Locale.default`. + + ! What is a Character? + A character is defined as an Extended Grapheme Cluster, see Unicode + Standard Annex 29. This is the smallest unit that still has semantic + meaning in most text-processing applications. > Example Converting a text to upper case in the default locale: diff --git a/distribution/std-lib/Standard/src/Base/Data/Text/Split_Kind.enso b/distribution/std-lib/Standard/src/Base/Data/Text/Split_Kind.enso index c4e1026fc2..38210a9a08 100644 --- a/distribution/std-lib/Standard/src/Base/Data/Text/Split_Kind.enso +++ b/distribution/std-lib/Standard/src/Base/Data/Text/Split_Kind.enso @@ -2,12 +2,16 @@ from Standard.Base import all ## The type of split for splitting text. type Split_Kind + ## Split on unicode whitespace. type Whitespace + ## Split into lines. type Lines + ## Split into words. type Words - ## Split on a literal. + + ## Split on a literal text value. Text diff --git a/distribution/std-lib/Standard/src/Base/Data/Time/Date.enso b/distribution/std-lib/Standard/src/Base/Data/Time/Date.enso index 3a37296198..510c4b0173 100644 --- a/distribution/std-lib/Standard/src/Base/Data/Time/Date.enso +++ b/distribution/std-lib/Standard/src/Base/Data/Time/Date.enso @@ -12,8 +12,12 @@ polyglot java import org.enso.base.Time_Utils type Date - ## This type represents a date, often viewed as year-month-day. For example, - the value "2nd October 2007" can be stored in a `Date`. + ## This type represents a date, often viewed as year-month-day. + + Arguments: + - internal_local_date: The internal date representation. + + For example, the value "2nd October 2007" can be stored in a `Date`. This class does not store or represent a time or timezone. Instead, it is a description of the date, as used for birthdays. It cannot represent @@ -22,56 +26,93 @@ type Date type Date internal_local_date ## Get the year field. + + > Example + Get the current year. + Date.now.year year : Integer year = this . internal_local_date . getYear ## Get the month of year field, as a number from 1 to 12. + + > Example + Get the current month. + Date.now.month month : Integer month = this . internal_local_date . getMonthValue ## Get the day of month field. + + > Example + Get the current day. + Date.now.day day : Integer day = this . internal_local_date . getDayOfMonth ## Combine this date with time of day to create a point in time. + Arguments: + - time_of_day: The time to combine with the date to create a time. + - zone: The time-zone in which to create the time. + > Example Convert this date to midnight UTC time. Day.new 2020 2 3 . to_time Time_Of_Day.new Zone.utc to_time : Time_Of_Day -> Zone -> Time - to_time daytime (zone = Zone.system) = Time.time (this . internal_local_date . atTime daytime.internal_local_time . atZone zone.internal_zone_id) + to_time time_of_day (zone = Zone.system) = Time.time (this . internal_local_date . atTime time_of_day.internal_local_time . atZone zone.internal_zone_id) - ## Add specified amount of time to this instant. + ## Add the specified amount of time to this instant to get another date. + + Arguments: + - amount: The time duration to add to this instant. > Example Add 6 months to a local date. Date.new 2020 + 6.months + : Duration -> Date - + amount = if amount.is_time then Error.throw (Time.Time_Error "Date does not support time intervals") else Date (this . internal_local_date . plus amount.internal_period) + + amount = if amount.is_time then Error.throw (Time.Time_Error "Date does not support time intervals") else + Date (this . internal_local_date . plus amount.internal_period) - ## Subtract specified amount of time to this instant. + ## Subtract the specified amount of time from this instant to get another + date. + + Arguments: + - amount: The time duration to subtract from this date. > Example Subtract 7 days from a local date. Date.new 2020 - 7.days - : Duration -> Date - - amount = if amount.is_time then Error.throw (Time.Time_Error "Date does not support time intervals") else Date (this . internal_local_date . minus amount.internal_period) + - amount = if amount.is_time then Error.throw (Time.Time_Error "Date does not support time intervals") else + Date (this . internal_local_date . minus amount.internal_period) ## Format this date using the default formatter. + + > Example + Convert the current date to text. + Date.now.to_text to_text : Text to_text = Time_Utils.default_date_formatter . format this.internal_local_date ## A Date to Json conversion. + + > Example + Convert the current date to JSON. + Date.now.to_json to_json : Json.Object to_json = Json.from_pairs [["type", "Date"], ["day", this.day], ["month", this.month], ["year", this.year]] - ## Format this date using formatter text. + ## Format this date using the provided format specifier. - Patterns are based on a simple sequence of letters and symbols. For - example, "d MMM yyyy" will format "2011-12-03" as "3 Dec 2011". + Arguments: + - pattern: The text specifying the format for formatting the date. - For the list of accepted symbols in pattern refer to - `Base.Data.Time.Time.format` doc. + ? Pattern Syntax + Patterns are based on a simple sequence of letters and symbols. For + example, "d MMM yyyy" will format "2011-12-03" as "3 Dec 2011". + + For the list of accepted symbols in pattern refer to the + `Base.Data.Time.Time.format` doc. > Example Format "2020-06-02" as "2 June 2020" @@ -95,33 +136,34 @@ type Date format : Text -> Text format pattern = DateTimeFormatter.ofPattern pattern . format this.internal_local_date -## Obtains an instance of `Date` from a text, such as "2007-12-03". +## Converts text containing a date into a Date object. Arguments: - - text: The textual content to parse as a date. + - text: The text to try and parse as a date. Returns a `Time_Error` if the provided `text` cannot be parsed using the provided `pattern`. - The text must represent a valid date and is parsed using the ISO-8601 - extended local date format. The format consists of: + ? Date Formatting + The text must represent a valid date and is parsed using the ISO-8601 + extended local date format. The format consists of: - - Four digits or more for the year. Years in the range 0000 to 9999 - will be pre-padded by zero to ensure four digits. Years outside - that range will have a prefixed positive or negative symbol. - - A dash - - Two digits for the month-of-year. This is pre-padded by zero to ensure two - digits. - - A dash - - Two digits for the day-of-month. This is pre-padded by zero to ensure two - digits. + - Four digits or more for the year. Years in the range 0000 to 9999 + will be pre-padded by zero to ensure four digits. Years outside + that range will have a prefixed positive or negative symbol. + - A dash + - Two digits for the month-of-year. This is pre-padded by zero to ensure + two digits. + - A dash + - Two digits for the day-of-month. This is pre-padded by zero to ensure two + digits. > Example Parse the date of 23rd December 2020. Date.parse "2020-12-23" > Example - Recover from the parse error. + Recover from an error due to a wrong format. Date.parse "my birthday" . catch e-> case e of Time.Error _ -> Date.new 2000 1 1 parse : Text -> Date ! Time.Time_Error @@ -130,18 +172,19 @@ parse text = Polyglot_Error err -> Error.throw (Time.Time_Error err.getMessage) x -> x -## Obtains an instance of `Date` from a text using custom format. +## Converts text containing a date into a Date object using a custom format. Arguments: - text: The textual content to parse as a time. - pattern: The pattern describing how to parse the text. - For the list of accepted symbols in pattern refer to - `Base.Data.Time.Time.format` doc. - Returns a `Time_Error` if the provided `text` cannot be parsed using the provided `pattern`. + ? Pattern Syntax + For the list of accepted symbols in pattern refer to the + `Base.Data.Time.Time.format` doc. + > Example Parse "1999-1-1" as Date. Date.parse_format "1999-1-1" "yyyy-M-d" @@ -159,18 +202,27 @@ parse_format text pattern = x -> x ## Obtains the current date from the system clock in the system timezone. + + > Example + Get the current date. + Date.now now : Date now = Date LocalDate.now ## Alias for `now`. + + > Example + Get the current date. + Date.today today : Date today = here.now -## Obtains an instance of `Date` from a year, month and day. +## Constructs a new Date from a year, month, and day. - - month - the month-of-year to represent, from 1 (January) to 12 (December) - - day - the day-of-month to represent, from 1 to 31 and must be valid for the - year and month + Arguments + - month: The month-of-year to represent, from 1 (January) to 12 (December). + - day: The day-of-month to represent, from 1 to 31. It must be valid for the + year and month. Returns a `Time_Error` if the provided time is not valid. diff --git a/distribution/std-lib/Standard/src/Base/Data/Time/Duration.enso b/distribution/std-lib/Standard/src/Base/Data/Time/Duration.enso index 7dab30cfbb..6ee28e5dd4 100644 --- a/distribution/std-lib/Standard/src/Base/Data/Time/Duration.enso +++ b/distribution/std-lib/Standard/src/Base/Data/Time/Duration.enso @@ -9,9 +9,17 @@ type Duration ## An amount of time in terms of years, months, days, hours, minutes, seconds and nanoseconds. + + Arguments: + - internal_period: The internal representation of the time as a period. + - internal_duration: The internal representation of the time as a + duration. type Duration internal_period internal_duration - ## Add specified amount of time to this duration. + ## Add the specified amount of time to this duration. + + Arguments: + - that: The duration to add to `this`. > Example Add 6 seconds to a duration of 3 minutes @@ -21,9 +29,12 @@ type Duration Add 12 hours to a duration of a month. 1.month + 12.hours + : Duration -> Duration - + other = Duration (this.internal_period . plus other.internal_period . normalized) (this.internal_duration . plus other.internal_duration) + + that = Duration (this.internal_period . plus that.internal_period . normalized) (this.internal_duration . plus that.internal_duration) - ## Subtract specified amount of time from this duration. + ## Subtract the specified amount of time from this duration. + + Arguments: + - that: The duration to subtract from `this`. > Example Subtract 11 months from a duration of 3 years @@ -33,37 +44,69 @@ type Duration Substract 30 minutes from a duration of 7 months. 7.months - 30.minutes - : Duration -> Duration - - other = Duration (this.internal_period . minus other.internal_period . normalized) (this.internal_duration . minus other.internal_duration) + - that = Duration (this.internal_period . minus that.internal_period . normalized) (this.internal_duration . minus that.internal_duration) - ## Get the amount of nanoseconds of this duration. + ## Get the portion of the duration expressed in nanoseconds. + + > Example + Get the portion of the duration expressed in nanoseconds. + 1.nanosecond.nanoseconds nanoseconds : Integer nanoseconds = this.internal_duration . toNanosPart - ## Get the amount of milliseconds of this duration. + ## Get the portion of the duration expressed in milliseconds. + + > Example + Get the portion of the duration expressed in milliseconds. + 1.millisecond.milliseconds milliseconds : Integer milliseconds = this.internal_duration . toMillisPart - ## Get the amount of minutes of this duration. + ## Get the portion of the duration expressed in seconds. + + > Example + Get the portion of the duration expressed in seconds. + 1.second.seconds seconds : Integer seconds = this.internal_duration . toSecondsPart - ## Get the amount of minutes of this duration. + ## Get the portion of the duration expressed in minutes. + + > Example + Get the portion of the duration expressed in minutes. + 1.minute.minutes minutes : Integer minutes = this.internal_duration . toMinutesPart - ## Get the amount of hours of this duration. + ## Get the portion of the duration expressed in hours. + + > Example + Get the portion of the duration expressed in hours. + 1.hour.hours hours : Integer hours = this.internal_duration . toHours - ## Get the amount of days of this duration. + ## Get the portion of the duration expressed in days. + + > Example + Get the portion of the duration expressed in days. + 1.day.days days : Integer days = this.internal_period . getDays - ## Get the amount of months of this duration. + ## Get the portion of the duration expressed in months. + + > Example + Get the portion of the duration expressed in months. + 1.month.months months : Integer months = this.internal_period . getMonths - ## Get the amount of days of this duration. + ## Get the portion of the duration expressed in years. + + > Example + Get the portion of the duration expressed in years. + 1.year.years years : Integer years = this.internal_period . getYears @@ -81,6 +124,10 @@ type Duration to_vector = [this.years, this.months, this.days, this.hours, this.minutes, this.seconds, this.nanoseconds] ## A Duration to Json conversion. + + > Example + Convert a duration of 10 seconds to Json. + 10.seconds.to_json to_json : Json.Object to_json = b = Vector.new_builder @@ -95,18 +142,37 @@ type Duration Json.from_pairs b.to_vector ## Check if this duration is date-based. + + > Example + Check if the duration of 10 seconds is date-based. + 10.seconds.is_date is_date : Boolean is_date = (this.years==0 . not) || (this.months==0 . not) || (this.days==0 . not) ## Check if this duration is time-based. + + > Example + Check if the duration of 10 seconds is time-based. + 10.seconds.is_time is_time : Boolean is_time = (this.hours==0 . not) || (this.minutes==0 . not) || (this.seconds==0 . not) || (this.nanoseconds==0 . not) ## Check if this duration represents an empty time-span. + + > Example + Check if the duration of 10 seconds is empty. + 10.seconds.is_empty is_empty : Boolean is_empty = this.is_date.not && this.is_time.not - ## Check the durations equality. + ## Check two durations for equality. + + Arguments: + - that: The duration to compare against `this`. + + > Examples + Check if 60 seconds and 1 minute are equal. + 60.seconds == 1.minute == : Duration -> Boolean == that = this.to_vector == that.to_vector @@ -176,9 +242,14 @@ Integer.years = this.year ## Create an interval representing the duration between two points in time. + Arguments: + - start_inclusive: The start time of the duration. + - end_inclusife: The end time of the duration. + > Example An hour interval between two points in time. Duration.between Time.now (Time.new 2010 10 20) between : Time -> Time -> Duration between start_inclusive end_exclusive = Duration (Java_Period.ofDays 0 . normalized) (Java_Duration.between start_inclusive.internal_zoned_date_time end_exclusive.internal_zoned_date_time) + diff --git a/distribution/std-lib/Standard/src/Base/Data/Time/Time.enso b/distribution/std-lib/Standard/src/Base/Data/Time/Time.enso index a92515be98..6f6df9e22f 100644 --- a/distribution/std-lib/Standard/src/Base/Data/Time/Time.enso +++ b/distribution/std-lib/Standard/src/Base/Data/Time/Time.enso @@ -12,7 +12,12 @@ polyglot java import org.enso.base.Time_Utils type Time_Error - ## Error produced while working with time. + ## UNSTABLE + + An error produced while working with time. + + Arguments: + - error_message: The message for the error. type Time_Error error_message type Time @@ -20,6 +25,9 @@ type Time ## A date-time with a timezone in the ISO-8601 calendar system, such as "2007-12-03T10:15:30+01:00 Europe/Paris". + Arguments: + - internal_zoned_date_time: The internal repreentation of the time. + Time is a representation of a date-time with a timezone. This class stores all date and time fields, to a precision of nanoseconds, and a timezone, with a zone offset used to handle ambiguous local @@ -29,55 +37,108 @@ type Time the Europe/Paris timezone" can be stored as `Time`. type Time internal_zoned_date_time - ## Get the year field. + ## Get the year portion of the time. + + > Example + Get the current year. + Time.now.year year : Integer year = this . internal_zoned_date_time . getYear - ## Get the month of year field from 1 to 12. + ## Get the month portion of the time as a number from 1 to 12. + + > Example + Get the current month. + Time.now.month month : Integer month = this . internal_zoned_date_time . getMonthValue - ## Get the day of month field. + ## Get the day portion of the time. + + > Example + Get the current day. + Time.now.day day : Integer day = this . internal_zoned_date_time . getDayOfMonth - ## Get the hour of day field. + ## Get the hour portion of the time. + + > Example + Get the current hour. + Time.now.hour hour : Integer hour = this . internal_zoned_date_time . getHour - ## Get the minute of hour field. + ## Get the minute portion of the time. + + > Example + Get the current minute. + Time.now.minute minute : Integer minute = this . internal_zoned_date_time . getMinute - ## Get the second of minute field + ## Get the second portion of the time. + + > Example + Get the current second. + Time.now.second second : Integer second = this . internal_zoned_date_time . getSecond - ## Get the nano-of-second field. + ## Get the nanosecond portion of the time. + + > Example + Get the current nanosecond. + Time.now.nanosecond nanosecond : Integer nanosecond = this . internal_zoned_date_time . getNano - ## Get the timezone. + ## Get the timezone for the time. + + > Example + Get the current timezone. + Time.now.zone zone : Zone zone = Zone.zone (this . internal_zoned_date_time . getZone) ## Return the number of seconds from the Unix epoch. + + > Example + Get the current number of seconds from the Unix epoch. + Time.now.to_epoch_seconds to_epoch_seconds : Integer to_epoch_seconds = this . internal_zoned_date_time . toEpochSecond ## Return the number of milliseconds from the Unix epoch. + + > Example + Get the current number of milliseconds from the unix epoch. + Time.now.to_epoch_milliseconds to_epoch_milliseconds : Integer to_epoch_milliseconds = this . internal_zoned_date_time . toInstant . toEpochMilli - ## Convert this point in time to time of day. + ## Convert this point in time to time of day, discarding the time zone + information. + + > Example + Convert the current time to a time of day. + Time.now.time_of_day time_of_day : Time_Of_Day time_of_day = Time_Of_Day.time_of_day this.internal_zoned_date_time.toLocalTime - ## Convert this point in time to date. + ## Convert this point in time to date, discarding the time of day + information. + + > Example + Convert the current time to a date. + Time.now.date date : Date date = Date.date this.internal_zoned_date_time.toLocalDate - ## Convert the time instant to a provided timezone. + ## Convert the time instant to the same instant in the provided time zone. + + Arguments: + - zone: The time-zone to convert the time instant into. > Example Convert time instance to -04:00 timezone. @@ -85,7 +146,10 @@ type Time at_zone : Zone -> Time at_zone zone = Time (this.internal_zoned_date_time . withZoneSameInstant zone.internal_zone_id) - ## Add specified amount of time to this instant. + ## Add the specified amount of time to this instant to produce a new instant. + + Arguments: + - amount: The amount of time to add to this instant. > Example Add 1 hour to a zoned date time. @@ -97,7 +161,11 @@ type Time + : Duration -> Time + amount = Time (this . internal_zoned_date_time . plus amount.internal_period . plus amount.internal_duration) - ## Subtract specified amount of time to this instant. + ## Subtract the specified amount of time from this instant to get a new + instant. + + Arguments: + - amount: The amount of time to subtract from this instant. > Example Subtract 10 days from a zoned date time. @@ -109,60 +177,72 @@ type Time - : Duration -> Time - amount = Time (this . internal_zoned_date_time . minus amount.internal_period . minus amount.internal_duration) - ## Format this time using the default formatter. + ## Convert this time to text using the default formatter. + + > Example + Convert the current time to text. + Time.now.to_text to_text : Text to_text = Time_Utils.default_time_formatter . format this.internal_zoned_date_time - ## A Time to Json conversion. + ## Convert the time to JSON. + + > Example + Convert the current time to JSON. + Time.now.to_json to_json : Json.Object to_json = Json.from_pairs [["type", "Time"], ["year", this.year], ["month", this.month], ["day", this.day], ["hour", this.hour], ["minute", this.minute], ["second", this.second], ["nanosecond", this.nanosecond], ["zone", this.zone]] - ## Format this time using formatter text. + ## Format this time as text using the specified format specifier. - Patterns are based on a simple sequence of letters and symbols. For - example, "d MMM uuuu" will format "2011-12-03" as "3 Dec 2011". + Arguments: + - pattern: The pattern that specifies how to format the time. - The list of accepted symbols with examples: + ? Pattern Syntax + Patterns are based on a simple sequence of letters and symbols. For + example, "d MMM uuuu" will format "2011-12-03" as "3 Dec 2011". - - 'G', era, "AD; Anno Domini" - - 'u', year, "2004; 04" - - 'y', year-of-era, "2004; 04" - - 'D', day-of-year, "189" - - 'M/L', month-of-year, "7; 07; Jul; July; J" - - 'd', day-of-month, "10" - - 'g', modified-julian-day, "2451334" - - 'Q/q', quarter-of-year, "3; 03; Q3; 3rd quarter" - - 'Y', week-based-year, "1996; 96" - - 'w', week-of-week-based-year, "27" - - 'W', week-of-month, "4" - - 'E', day-of-week, "Tue; Tuesday; T" - - 'e/c', localized day-of-week, "2; 02; Tue; Tuesday; T" - - 'F', day-of-week-in-month, "3" - - 'a', am-pm-of-day, "PM" - - 'h', clock-hour-of-am-pm (1-12), "12" - - 'K', hour-of-am-pm (0-11), "0" - - 'k', clock-hour-of-day (1-24), "24" - - 'H', hour-of-day (0-23), "0" - - 'm', minute-of-hour, "30" - - 's', second-of-minute, "55" - - 'S', fraction-of-second, "978" - - 'A', milli-of-day, "1234" - - 'n', nano-of-second, "987654321" - - 'N', nano-of-day, "1234000000" - - 'V', time-zone ID, "America/Los_Angeles; Z; -08:30" - - 'v', generic time-zone name, "Pacific Time; PT" - - 'z', time-zone name, "Pacific Standard Time; PST" - - 'O', localized zone-offset, "GMT+8; GMT+08:00; UTC-08:00" - - 'X', zone-offset 'Z' for zero, "Z; -08; -0830; -08:30; -083015; -08:30:15" - - 'x', zone-offset, "+0000; -08; -0830; -08:30; -083015; -08:30:15" - - 'Z', zone-offset, "+0000; -0800; -08:00" - - 'p', pad next, "1" - - ''', (single quote) escape for text, "'Text'" - - '''', (double quote) single quote, "'" - - '[', optional section start - - ']', optional section end + The list of accepted symbols with examples: - The count of pattern letters determines the format. + - 'G', era, "AD; Anno Domini" + - 'u', year, "2004; 04" + - 'y', year-of-era, "2004; 04" + - 'D', day-of-year, "189" + - 'M/L', month-of-year, "7; 07; Jul; July; J" + - 'd', day-of-month, "10" + - 'g', modified-julian-day, "2451334" + - 'Q/q', quarter-of-year, "3; 03; Q3; 3rd quarter" + - 'Y', week-based-year, "1996; 96" + - 'w', week-of-week-based-year, "27" + - 'W', week-of-month, "4" + - 'E', day-of-week, "Tue; Tuesday; T" + - 'e/c', localized day-of-week, "2; 02; Tue; Tuesday; T" + - 'F', day-of-week-in-month, "3" + - 'a', am-pm-of-day, "PM" + - 'h', clock-hour-of-am-pm (1-12), "12" + - 'K', hour-of-am-pm (0-11), "0" + - 'k', clock-hour-of-day (1-24), "24" + - 'H', hour-of-day (0-23), "0" + - 'm', minute-of-hour, "30" + - 's', second-of-minute, "55" + - 'S', fraction-of-second, "978" + - 'A', milli-of-day, "1234" + - 'n', nano-of-second, "987654321" + - 'N', nano-of-day, "1234000000" + - 'V', time-zone ID, "America/Los_Angeles; Z; -08:30" + - 'v', generic time-zone name, "Pacific Time; PT" + - 'z', time-zone name, "Pacific Standard Time; PST" + - 'O', localized zone-offset, "GMT+8; GMT+08:00; UTC-08:00" + - 'X', zone-offset 'Z' for zero, "Z; -08; -0830; -08:30; -083015; -08:30:15" + - 'x', zone-offset, "+0000; -08; -0830; -08:30; -083015; -08:30:15" + - 'Z', zone-offset, "+0000; -0800; -08:00" + - 'p', pad next, "1" + - ''', (single quote) escape for text, "'Text'" + - '''', (double quote) single quote, "'" + - '[', optional section start + - ']', optional section end + + The count of pattern letters determines the format. > Example Format "2020-10-08T16:41:13+03:00[Europe/Moscow]" as "2020-10-08T16:41:13+03:00[Europe/Moscow]" @@ -184,17 +264,18 @@ type Time Arguments: - text: The text representing the time to be parsed. - The text must represent a valid date-time and is parsed using the ISO-8601 - extended offset date-time format to add the timezone. The section in square - brackets is not part of the ISO-8601 standard. The format consists of: + ? Valid Formatting + The text must represent a valid date-time and is parsed using the ISO-8601 + extended offset date-time format to add the timezone. The section in square + brackets is not part of the ISO-8601 standard. The format consists of: - - The ISO offset date time. - - If the zone ID is not available or is a zone offset then the format is - complete. - - An open square bracket '['. - - The zone ID. This is not part of the ISO-8601 standard. Parsing is case - sensitive. - - A close square bracket ']'. + - The ISO offset date time. + - If the zone ID is not available or is a zone offset then the format is + complete. + - An open square bracket '['. + - The zone ID. This is not part of the ISO-8601 standard. Parsing is case + sensitive. + - A close square bracket ']'. This method will return a `Time_Error` if the provided time cannot be parsed using the above format. @@ -225,7 +306,7 @@ parse text = Polyglot_Error err -> Error.throw (Time_Error err.getMessage) x -> x -## Obtains an instance of Time from a text using custom format. +## Converts text to a time using a provided format specifier. Arguments: - text: The text to parse as a time of day, using the specified pattern. @@ -234,8 +315,9 @@ parse text = Returns a `Time_Error` if the provided text cannot be parsed using the provided pattern and locale. - - For the list of accepted symbols in pattern refer to `Time.format` doc. + + ? Pattern Syntax + For the list of accepted symbols in pattern refer to `Time.format` doc. > Example Parse "2020-05-06 04:30:20" as Time @@ -251,6 +333,10 @@ parse_format text pattern locale=Locale.default = x -> x ## Obtains the current date-time from the system clock in the system timezone. + + > Example + Get the current time + Time.now now : Time now = Time ZonedDateTime.now diff --git a/distribution/std-lib/Standard/src/Base/Data/Time/Time_Of_Day.enso b/distribution/std-lib/Standard/src/Base/Data/Time/Time_Of_Day.enso index 989340fe43..99174fc1c1 100644 --- a/distribution/std-lib/Standard/src/Base/Data/Time/Time_Of_Day.enso +++ b/distribution/std-lib/Standard/src/Base/Data/Time/Time_Of_Day.enso @@ -14,39 +14,71 @@ polyglot java import org.enso.base.Time_Utils type Time_Of_Day ## This type is a date-time object that represents a time, often viewed - as hour-minute-second. Time is represented to nanosecond precision. For - example, the value "13:45.30.123456789" can be stored in a `Time_Of_Day`. + as hour-minute-second. + + Arguments: + - internal_local_time: The internal representation of the time of day. + + Time is represented to nanosecond precision. For example, the value + "13:45.30.123456789" can be stored in a `Time_Of_Day`. type Time_Of_Day internal_local_time - ## Get the hour of day field. + ## Get the hour portion of the time of day. + + > Example + Get the current hour. + Time_Of_Day.now.hour hour : Integer hour = this . internal_local_time . getHour - ## Get the minute of hour field. + ## Get the minute portion of the time of day. + + > Example + Get the current minute. + Time_Of_Day.now.minute minute : Integer minute = this . internal_local_time . getMinute - ## Get the second of minute field. + ## Get the second portion of the time of day. + + > Example + Get the current second. + Time_Of_Day.now.second second : Integer second = this . internal_local_time . getSecond - ## Get the nanosecond of second field. + ## Get the nanosecond portion of the time of day. + + > Example + Get the current nanosecond. + Time_Of_Day.now.nanosecond nanosecond : Integer nanosecond = this . internal_local_time . getNano ## Extracts the time as the number of seconds, from 0 to 24 * 60 * 60 - 1. + + > Example + Convert the current time to seconds of the day. + Time_Of_Day.now.to_seconds to_seconds : Integer to_seconds = this . internal_local_time . toSecondOfDay ## Combine this time of day with a date to create a point in time. + Arguments: + - date: The date on which this time should occur. + - zone: The time-zone in which the time is specified. + > Example Convert local time to 1st January 2020 12:30 at system timezone. Time_Of_Day.new 12 30 . to_time (Date.new 2020) to_time : Date -> Zone -> Time to_time date (zone = Zone.system) = Time.time (this . internal_local_time . atDate date.internal_local_date . atZone zone.internal_zone_id) - ## Add specified amount of time to this instant. + ## Add the specified amount of time to this instant to get a new instant. + + Arguments: + - amount: The amount of time to add to this instant. > Example Add 3 seconds to a local time. @@ -54,7 +86,11 @@ type Time_Of_Day + : Duration -> Time_Of_Day + amount = if amount.is_date then Error.throw (Time.Time_Error "Time_Of_Day does not support date intervals") else Time_Of_Day (this . internal_local_time . plus amount.internal_duration) - ## Subtract specified amount of time to this instant. + ## Subtract the specified amount of time from this instant to get a new + instant. + + Arguments: + - amount: The amount of time to subtract from this instant. > Example Subtract 12 hours from a local time. @@ -62,21 +98,33 @@ type Time_Of_Day - : Duration -> Time_Of_Day - amount = if amount.is_date then Error.throw (Time.Time_Error "Time_Of_Day does not support date intervals") else Time_Of_Day (this . internal_local_time . minus amount.internal_duration) - ## Format this time of day using the default formatter. + ## Format this time of day as text using the default formatter. + + > Example + Convert the current time to text. + Time_Of_Day.now.to_text to_text : Text to_text = Time_Utils.default_time_of_day_formatter . format this.internal_local_time ## A Time_Of_Day to Json conversion. + + > Example + Convert the current time to JSON. + Time_Of_Day.now.to_text to_json : Json.Object to_json = Json.from_pairs [["type", "Time_Of_Day"], ["hour", this.hour], ["minute", this.minute], ["second", this.second], ["nanosecond", this.nanosecond]] - ## Format this time of day using formatter text. + ## Format this time of day using the provided formatter pattern. - Patterns are based on a simple sequence of letters and symbols. For - example, "HH-mm-ss.SSS" will format "16:21:10" as "16-21-10.323". + Arguments: + - pattern: The pattern specifying how to format the time of day. - For the list of accepted symbols in pattern refer to - `Base.Data.Time.Time.format` doc. + ? Pattern Syntax + Patterns are based on a simple sequence of letters and symbols. For + example, "HH-mm-ss.SSS" will format "16:21:10" as "16-21-10.323". + + For the list of accepted symbols in pattern refer to the + `Base.Data.Time.Time.format` doc. > Example Format "16:21:10" as "16:21:00.1234" @@ -108,22 +156,24 @@ type Time_Of_Day Returns a `Time_Error` if the provided text cannot be parsed using the default format. - The text must represent a valid time and is parsed using the ISO-8601 - extended local time format. The format consists of: + ? Valid Time Format + The text must represent a valid time and is parsed using the ISO-8601 + extended local time format. The format consists of: - - Two digits for the hour-of-day. This is pre-padded by zero to ensure two - digits. - - A colon - - Two digits for the minute-of-hour. This is pre-padded by zero to ensure two - digits. - - If the second-of-minute is not available then the format is complete. - - A colon - - Two digits for the second-of-minute. This is pre-padded by zero to ensure - two digits. - - If the nano-of-second is zero or not available then the format is complete. - - A decimal point - - One to nine digits for the nano-of-second. As many digits will be output as - required. + - Two digits for the hour-of-day. This is pre-padded by zero to ensure two + digits. + - A colon + - Two digits for the minute-of-hour. This is pre-padded by zero to ensure + two digits. + - If the second-of-minute is not available then the format is complete. + - A colon + - Two digits for the second-of-minute. This is pre-padded by zero to ensure + two digits. + - If the nano-of-second is zero or not available then the format is + complete. + - A decimal point + - One to nine digits for the nano-of-second. As many digits will be output + as required. > Example Get the time 15:05:30. @@ -149,8 +199,9 @@ parse text = Returns a `Time_Error` if the provided text cannot be parsed using the provided pattern and locale. - For the list of accepted symbols in pattern refer to - `Base.Data.Time.Time.format` doc. + ? Pattern Syntax + For the list of accepted symbols in pattern refer to the + `Base.Data.Time.Time.format` doc. > Example Parse "04:30:20" as Time_Of_Day. @@ -167,16 +218,21 @@ parse_format text pattern locale=Locale.default = x -> x ## Obtains the current time from the system clock in the default time-zone. + + > Example + Get the current time in the default time zone. + Time_Of_Day.now now : Time_Of_Day now = Time_Of_Day LocalTime.now ## Obtains an instance of `Time_Of_Day` from an hour, minute, second and nanosecond. - - hour - the hour-of-day to represent, from 0 to 23 - - minute - the minute-of-hour to represent, from 0 to 59 - - second - the second-of-minute to represent, from 0 to 59 - - nanosecond - the nano-of-second to represent, from 0 to 999,999,999 + Arguments: + - hour: The hour-of-day to represent, from 0 to 23. + - minute: The minute-of-hour to represent, from 0 to 59. + - second: The second-of-minute to represent, from 0 to 59. + - nanosecond: The nano-of-second to represent, from 0 to 999,999,999. Returns a `Time_Error` if the provided time is not a valid time. diff --git a/distribution/std-lib/Standard/src/Base/Data/Time/Zone.enso b/distribution/std-lib/Standard/src/Base/Data/Time/Zone.enso index 1b73e56840..b1ee4f414a 100644 --- a/distribution/std-lib/Standard/src/Base/Data/Time/Zone.enso +++ b/distribution/std-lib/Standard/src/Base/Data/Time/Zone.enso @@ -7,20 +7,35 @@ type Zone ## A type representing a time zone. + Arguments: + - internal_zone_id: The identifier for the internal zone of the + representation. + A time zone can be eiter offset-based like "-06:00" or id-based like "Europe/Paris". type Zone internal_zone_id ## Get the unique timezone ID. + + > Example + Get the unique identifier for your system's current timezone. + Zone.system.zone_id zone_id : Text zone_id = this.internal_zone_id . getId - ## A Zone to Json conversion + ## Convert the time zone to JSON. + + > Example + Convert your system's current timezone to JSON. + Zone.system.to_json to_json : Json.Object to_json = Json.from_pairs [["type", "Zone"], ["id", this.zone_id]] ## This method parses the ID producing a `Zone`. + Arguments: + - text: The text representing a zone identifier. + > Example Get Central European Time. Zone.parse "CET" @@ -40,27 +55,41 @@ parse : Text -> Zone parse text = Zone (ZoneId.of text) ## The system default timezone. + + > Example + Get the system default timezone. + Zone.system system : Zone system = Zone ZoneId.systemDefault -## The system default timezone. +## The system's local timezone. + + > Example + Get the system's local timezone. + Zone.local local : Zone local = here.system -## UTC time zone. +## The UTC timezone. + + > Example + Get the UTC timezone. + Zone.utc utc : Zone utc = here.parse "UTC" -## Obtains an instance of `Zone` using an offset in hours, minutes and seconds. +## Obtains an instance of `Zone` using an offset in hours, minutes and seconds + from the UTC zone. - - the timezone offset in hours, from -18 to +18 - - the timezone offset in minutes, from 0 to ±59, sign matches hours and - seconds - - the timezone offset in seconds, from 0 to ±59, sign matches hours and - minutes + Arguments: + - hours: The timezone offset in hours from UTC, from -18 to +18. + - minutes: The timezone offset in minutes from the nearest hour, from 0 to + ±59. The sign must match that of the hours argument. + - seconds: The timezone offset in seconds from the nearest minute, from 0 to + ±59. The sign must match that of the minutes argument. > Example - Get time zone 1 hour 1 minute and 50 seconds of Greenwich/UTC. + Get time zone 1 hour 1 minute and 50 seconds from UTC. Zone.new 1 1 50 new : Integer -> Integer -> Integer -> Zone new (hours = 0) (minutes = 0) (seconds = 0) = diff --git a/distribution/std-lib/Standard/src/Base/Data/Vector.enso b/distribution/std-lib/Standard/src/Base/Data/Vector.enso index d227f0bc6f..dab8ab62a2 100644 --- a/distribution/std-lib/Standard/src/Base/Data/Vector.enso +++ b/distribution/std-lib/Standard/src/Base/Data/Vector.enso @@ -4,8 +4,10 @@ from Builtins import Array ## Creates a new vector of the given length, initializing elements using the provided constructor function. - The constructor function is called with the consecutive indices - (0-based) of the vector elements. + Arguments: + - length: The length of the vector (>= 0). + - constructor: A function taking the index in the vector and returning an + item for that index in the vector. > Example To create a vector containing the numbers 1 through 50: @@ -23,6 +25,10 @@ new length constructor = ## Creates a new vector of the given length, filling the elements with the provided constant. + Arguments: + - length: The length of the vector (>= 0). + - constructor: A value fo be placed into each element of the vector. + > Example A vector containing 50 elements, each being the number `42`, can be created by: @@ -58,8 +64,12 @@ fill length ~item = new_builder : Builder new_builder = Builder.new -## Converts a polyglot value representing an array into a vector. This is - useful when wrapping polyglot APIs for further use in Enso. +## Converts a polyglot value representing an array into a vector. + + Arguments: + - arr: The array value to wrap into a vector. + + This is useful when wrapping polyglot APIs for further use in Enso. from_polyglot_array : Any -> Vector.Vector from_polyglot_array arr = here.new arr.length (arr.at _) @@ -89,6 +99,9 @@ type Vector ## Gets an element from the vector at a specified index (0-based). + Arguments: + - index: The location in the vector to get the element from. + > Example To get the second element of the vector `[1, 2, 3]`, use: [1, 2, 3].at 1 @@ -98,6 +111,10 @@ type Vector ## Combines all the elements of the vector, by iteratively applying the passed function with next elements of the vector. + Arguments: + - init: The initial value for the fold. + - function: A function taking two elements and combining them. + In general, the result of [l0, l1, ..., ln] . fold init f is the same as @@ -108,12 +125,16 @@ type Vector vector: [0, 1, 2] . fold 0 (+) fold : Any -> (Any -> Any -> Any) -> Any - fold initial function = + fold init function = arr = this.to_array f = acc -> ix -> function acc (arr.at ix) - 0.up_to this.length . fold initial f + 0.up_to this.length . fold init f ## Combines all the elements of a non-empty vector using a binary operation. + + Arguments: + - function: A binary operation that takes two items and combines them. + If the vector is empty, it throws Nothing. > Example @@ -128,8 +149,10 @@ type Vector ## Checks whether a predicate holds for at least one element of this vector. - A predicate is a function that takes an element from the vector and - returns a boolean value. + Arguments: + - predicate: A function that takes a list element and returns a boolean + value that says whether that value satisfies the conditions of the + function. > Example Checking if any element of the list is larger than 3. @@ -142,10 +165,12 @@ type Vector go 0 False ## Returns the first element of the vector that satisfies the predicate or - If no elements of the vector satisfy the predicate, it throws nothing. + if no elements of the vector satisfy the predicate, it throws nothing. - A predicate is a function that takes an element from the vector and - returns a boolean value. + Arguments: + - predicate: A function that takes a list element and returns a boolean + value that says whether that value satisfies the conditions of the + function. > Example Finding a first element of the list that is larger than 3. @@ -162,8 +187,11 @@ type Vector ## Checks whether a predicate holds for at least one element of this vector. - A predicate is a function that takes an element from the vector and - returns a boolean value. + + Arguments: + - predicate: A function that takes a list element and returns a boolean + value that says whether that value satisfies the conditions of the + function. > Example Checking if any element of the list is larger than 3. @@ -173,6 +201,11 @@ type Vector ## Checks whether a predicate holds for all elements in this vector. + Arguments: + - predicate: A function that takes a list element and returns a boolean + value that says whether that value satisfies the conditions of the + function. + > Example Check if all elements in the vector are less than zero. [-1, 1, 5, 8].all (< 0) @@ -181,6 +214,9 @@ type Vector ## Checks whether this vector contains a given value as an element. + Arguments: + - elem: The item to see if it exists in the vector. + > Example Checking if the vector contains the number 72. [1, 383, 72, 301].contains 72 @@ -207,8 +243,10 @@ type Vector ## Selects all elements of this vector which satisfy a predicate. - A predicate is a function that takes an element from the vector and - returns a boolean value. + Arguments: + - predicate: A function that takes a list element and returns a boolean + value that says whether that value satisfies the conditions of the + function. > Example Selecting all elements that are greater than 3. @@ -221,6 +259,10 @@ type Vector ## Applies a function to each element of the vector, returning the vector of results. + Arguments: + - function: A function that takes an element in the vector and returns + some transformation of that element. + > Example In the following example, we add `1` to each element of the vector: [1, 2, 3] . map +1 @@ -233,12 +275,14 @@ type Vector ## Applies a function to each element of the vector, returning the vector that contains all results concatenated. + Arguments: + - function: A function that takes an element in the vector, transforms + it, and returns a vector. + > Example In the following example, we replace each number `n` with itself repeated `n` times: [0, 1, 2] . flat_map (n -> Vector.fill n n) - The result of running the code above is: - [1, 2, 2] flat_map : (Any -> Vector) -> Vector flat_map function = mapped = this.map function @@ -252,13 +296,24 @@ type Vector ## Applies a function to each element of the vector, returning the vector of results. + Arguments: + - function: A function that takes an index and an item and calculates a + new value for at that index. + The function is called with both the element index as well as the element itself. - map_with_index : (Int -> Any -> Any) -> Vector + + > Example + Summing numbers with their indices in a vector. + [1, 2, 3].map_with_index (+) + map_with_index : (Integer -> Any -> Any) -> Vector map_with_index function = here.new this.length i-> function i (this.at i) ## Applies a function to each element of the vector. + Arguments: + - function: A function to apply to each element of the vector. + Unlike `map`, this method does not return the individual results, therefore it is only useful for side-effecting computations. @@ -273,6 +328,10 @@ type Vector ## Reverses the vector, returning a vector with the same elements, but in the opposite order. + + > Example + Reversing a two-element vector. + [1, 2].reverse reverse : Vector reverse = here.new this.length (i -> this.at (this.length - (1 + i))) @@ -289,12 +348,17 @@ type Vector tail_elems = 1.up_to this.length . fold "" folder "[" + (this.at 0 . to_text) + tail_elems + "]" - ## Checks whether this vector is equal to `that`. Two vectors are considered - equal, when they have the same length and their items are pairwise equal. + ## Checks whether this vector is equal to `that`. + + Arguments: + - that: The vector to compare this vector against. + + Two vectors are considered equal, when they have the same length and + their items are pairwise equal. > Example Comparing two vectors for equality (this case is false). - [1, 2, 3] == [2, 3, 4 + [1, 2, 3] == [2, 3, 4] == : Vector -> Boolean == that = eq_at i = this.at i == that.at i @@ -303,6 +367,9 @@ type Vector ## Concatenates two vectors, resulting in a new vector, containing all the elements of `this`, followed by all the elements of `that`. + Arguments: + - that: The vector to concatenate to the end of `this`. + > Example Concatenating two single-element vectors. [1] + [2] == [1, 2] @@ -323,7 +390,7 @@ type Vector > Example Add one element in front: - [2, 3].prepend 1 == [1, 2, 3] + [2, 3].prepend 1 == [1, 2, 3] prepend : Any -> Vector prepend element = [element] + this @@ -334,13 +401,16 @@ type Vector > Example Add one element to the end: - [1, 2].append 3 == [1, 2, 3] + [1, 2].append 3 == [1, 2, 3] append : Any -> Vector append element = this + [element] ## When `this` is a vector of text values, concatenates all the values by interspersing them with `separator`. + Arguments: + - separator: The text to use to join the textual elements of the vector. + > Example The following code returns "foo, bar, baz" ["foo", "bar", "baz"].join ", " @@ -352,6 +422,9 @@ type Vector ## Creates a new vector with the first `count` elements in `this` removed. + Arguments: + - count: The number of elements to drop from the start of `this`. + > Example The following code returns [2, 3, 4, 5] [1, 2, 3, 4, 5].drop_start 1 @@ -361,6 +434,9 @@ type Vector ## Creates a new vector with the last `count` elements in `this` removed. + Arguments: + - count: The number of elements to drop from the end of `this`. + > Example The following code returns [1, 2, 3] [1, 2, 3, 4, 5].drop_end 2 @@ -371,6 +447,9 @@ type Vector ## Creates a new vector, consisting of the first `count` elements on the left of `this`. + Arguments: + - count: The number of elements to take from the start of `this`. + > Example The following code returns [1, 2] [1, 2, 3, 4, 5].take_start 2 @@ -381,6 +460,9 @@ type Vector ## Creates a new vector, consisting of the last `count` elements on the right of `this`. + Arguments: + - count: The number of elements to take from the end of `this`. + > Example The following code returns [3, 4, 5] [1, 2, 3, 4, 5].take_end 3 @@ -390,12 +472,20 @@ type Vector ## Performs a pair-wise operation passed in `function` on consecutive elements of `this` and `that`. + + Arguments: + - that: The vector to zip with `this`. + - function: The function used to combine pairwise elements of `this` and + `that`. + The result of this function is a vector of length being the shorter of `this` and `that`, containing results of calling `function`. > Example To pairwise-sum two vectors: [1, 2, 3].zip [4, 5, 6] (+) == [5, 7, 9] + + > Example When the `function` is not provided, it defaults to creating a pair of both elements: [1, 2, 3].zip [4, 5, 6] == [[1, 4], [2, 5], [3, 6]] @@ -405,32 +495,41 @@ type Vector here.new len i-> function (this.at i) (that.at i) ## Extend `this` vector to the length of `n` appending elements `elem` to - the end. If the new length `n` is less than existing length, `this` - vector is returned. + the end. + + Arguments: + - n: The length to pad `this` out to. + - elem: The element to fill the new padded slots with. + + If the new length `n` is less than existing length, `this` vector is + returned. > Example Extending vector to the length of 5 returns `[1, 2, 3, 0, 0]` - [1, 2, 3].pad 5 0 + [1, 2, 3].pad 5 0 + > Example Extending vector to the length of 5 returns `[1, 2, 3, 4, 5]` - [1, 2, 3, 4, 5].pad 5 0 + [1, 2, 3, 4, 5].pad 5 0 pad : Integer -> Any -> Vector pad n elem = if this.length >= n then this else this + (here.fill n-this.length elem) ## Vector to JSON conversion. + + > Example + Convert a vector of numbers to JSON. + [1, 2, 3].to_json to_json : Json.Array to_json = Json.Array (this.map .to_json) - ## Get the first element from the vector. + ## Get the first element from the vector, or an error `Nothing` if the + vector is empty. > Example The following code returns 1. [1, 2, 3, 4].head - > Example - Empty vectors return `Nothing`. - [].head == Nothing head : Any ! Nothing head = if this.length >= 1 then this.at 0 else Error.throw Nothing @@ -439,10 +538,6 @@ type Vector > Example The following code returns [2, 3, 4]. [1, 2, 3, 4].tail - - > Example - Empty vectors return `Nothing`. - [].tail == Nothing tail : Vector ! Nothing tail = if this.length >= 1 then this.drop_start 1 else Error.throw Nothing @@ -451,38 +546,30 @@ type Vector > Example The following code returns [1, 2, 3]. [1, 2, 3, 4].init - - > Example - Empty vectors return `Nothing`. - [].init == Nothing init : Vector ! Nothing init = if this.length >= 1 then this.drop_end 1 else Error.throw Nothing - ## Get the last element of the vector. + ## Get the last element of the vector, or an error `Nothing` if the vector + is empty. > Example The following code returns 4. [1, 2, 3, 4].last - - > Example - Empty vectors return `Nothing`. - [].last == Nothing last : Vector ! Nothing last = if this.length >= 1 then (this.take_end 1).at 0 else Error.throw Nothing - ## Get the first element from the vector. + ## Get the first element from the vector, or an error `Nothing` if the + vector is empty. > Example The following code returns 1. [1, 2, 3, 4].first - - > Example - Empty vectors return `Nothing`. - [].first == Nothing first : Vector ! Nothing first = this.head - ## Get the second element from the vector. + ## Get the second element from the vector, or an error `Nothing` if the + vector doesn't have a second element. + Useful when tuples are implemented as vectors. > Example @@ -506,11 +593,11 @@ type Vector ## Sort the Vector. Arguments: - - `on`: A projection from the element type to the value of that element + - on: A projection from the element type to the value of that element being sorted on. - - `by`: A function that compares the result of applying `on` to two + - by: A function that compares the result of applying `on` to two elements, returning an Ordering to compare them. - - `order`: The order in which the vector elements are sorted. + - order: The order in which the vector elements are sorted. By default, elements are sorted in ascending order, using the comparator `compare_to`. A custom comparator may be passed to the sort function. @@ -518,11 +605,12 @@ type Vector This is a stable sort, meaning that items that compare the same will not have their order changed by the sorting process. - The complexities for this sort are: - - *Worst-Case Time:* `O(n * log n)` - - *Best-Case Time:* `O(n)` - - *Average Time:* `O(n * log n)` - - *Worst-Case Space:* `O(n)` additional + ! Computational Complexity + The complexities for this sort are: + - *Worst-Case Time:* `O(n * log n)` + - *Best-Case Time:* `O(n)` + - *Average Time:* `O(n * log n)` + - *Worst-Case Space:* `O(n)` additional ? Implementation Note The sort implementation is based upon an adaptive, iterative mergesort @@ -560,46 +648,69 @@ type Vector Vector new_vec_arr - ## Transform the vector into text for displaying as part of its default + ## UNSTABLE + + Transform the vector into text for displaying as part of its default visualization. to_default_visualization_data : Text to_default_visualization_data = json = this.take_start 100 . to_json json.to_text -## A builder type for Enso vectors. - - A vector builder is a mutable data structure, that allows to gather a - number of elements and then convert them to a vector. This is - particularly useful when the number of elements is not known upfront. - - > Example - In the following example we'll read items from the standard input, - until the string "end" is entered by the user and then return a vector - containing all items. - from Standard.Base import all - - main = - builder = Vector.new_builder - do_read = - item = IO.readln - if item == "end" then Nothing else - builder.append item - do_read - do_read - vec = builder.to_vector - IO.println vec type Builder + ## A builder type for Enso vectors. + + Arguments: + - to_array: The accumulator for the new vector. + - length: The current length of the vector being built. + + A vector builder is a mutable data structure, that allows to gather a + number of elements and then convert them to a vector. This is + particularly useful when the number of elements is not known upfront. + + > Example + In the following example we'll read items from the standard input, + until the string "end" is entered by the user and then return a vector + containing all items. + from Standard.Base import all + + main = + builder = Vector.new_builder + do_read = + item = IO.readln + if item == "end" then Nothing else + builder.append item + do_read + do_read + vec = builder.to_vector + IO.println vec type Builder to_array length ## Creates a new builder. + + > Example + Make a new builder + Vector.new_builder + new : Builder new = Builder (Array.new 1) 0 ## Returns the current capacity (i.e. the size of the underlying storage) of this builder. + + > Example + Get the capacity of a new builder. + Vector.new_builder.capacity + capacity : Integer capacity = this.to_array.length ## Appends a new element into this builder. + + Arguments: + - item: The item to append to the vector builder. + + > Example + Append an item to a vector builder. + Vector.new_builder.append 10 append : Any -> Nothing append item = case this.capacity > this.length of True -> @@ -616,6 +727,14 @@ type Builder Nothing ## Converts this builder to a vector containing all the appended elements. + + > Example + Use a builder to add elements to and then create a vector. + bldr = Vector.new_builder + bldr.append 1 + bldr.append 10 + bldr.append 100 + bldr.to_vector to_vector : Vector to_vector = old_array = this.to_array @@ -624,3 +743,19 @@ type Builder new_array.set_at i (old_array.at i) Nothing Vector new_array + +## UNSTABLE + + An error for when an index is out of bounds in a vector. + + Arguments: + - index: The requested index in the vector. + - length: The length of the vector. +type Index_Out_Of_Bounds_Error index length + +## UNSTABLE + + Pretty prints an index out of bounds error. +Index_Out_Of_Bounds_Error.to_display_text : Text +Index_Out_Of_Bounds_Error.to_display_text = + "The index " + this.index.to_text + " is out of bounds in a vector with length " + this.length.to_text + "." diff --git a/distribution/std-lib/Standard/src/Base/Error/Extensions.enso b/distribution/std-lib/Standard/src/Base/Error/Extensions.enso index 83317b5be3..37461841df 100644 --- a/distribution/std-lib/Standard/src/Base/Error/Extensions.enso +++ b/distribution/std-lib/Standard/src/Base/Error/Extensions.enso @@ -1,32 +1,51 @@ from Standard.Base import all -## Returns the method name of the method that could not be found. +## ADVANCED + UNSTABLE + + Returns the method name of the method that could not be found. No_Such_Method_Error.method_name : Text No_Such_Method_Error.method_name = Meta.meta this.symbol . name -## A type used to represent that something has not yet been implemented. +## UNSTABLE + + A type used to represent that something has not yet been implemented. + + Arguments: + - message: The message describing what implementation is missing. type Unimplemented_Error message +## UNSTABLE + + Converts the unimplemented error to a human-readable error message. +Unimplemented_Error.to_display_text : Text +Unimplemented_Error.to_display_text = "An implementation is missing: " + this.message + ## A function that can be used to indicate that something hasn't been implemented yet. + + Arguments: + - message: A description of what implementation is missing. unimplemented : Text -> Void unimplemented message="" = Panic.throw (Unimplemented_Error message) -## Executes the provided handler on a dataflow error, or executes as identity on - a non-error value. +## Executes the provided handler on a dataflow error, or returns a non-error + value unchanged. Arguments: - handler: The function to call on this if it is an error value. By default this is identity. > Example - Catching an erroneous value to perform some operation on it. - (Time.Time_Error "Message").catch (err -> IO.println err) + Catching an erroneous value and getting the length of its message. + (Time.Time_Error "Message").catch (err -> err.error_message.length) Error.catch : (Error -> Any) -> Any Error.catch (handler = x->x) = this.catch_primitive handler -## Returns a display representation of the dataflow error on which it is called. +## UNSTABLE + + Returns a display representation of the dataflow error on which it is called. > Example Displaying a dataflow error. @@ -34,16 +53,19 @@ Error.catch (handler = x->x) = this.catch_primitive handler Error.to_default_visualization_data : Text Error.to_default_visualization_data = this.catch .to_default_visualization_data -## Returns a human-readable text representing this error. +## UNSTABLE + + Returns a human-readable text representing this error. Error.to_display_text : Text Error.to_display_text = "Error: " + (this.catch .to_display_text) -## Maps a dataflow error. - If the original value was a non-error value, it is not affected, but if it - was an error, the error is mapped through the provided function. +## Transforms an error. Arguments: - - f: The function to transform the error. + - f: The function used to transform the error. + + If `this` is a non-error value it is returned unchanged. However, if `this` + is an error, the error is transformed using the provided function > Example Wrapping an error value. @@ -51,11 +73,23 @@ Error.to_display_text = "Error: " + (this.catch .to_display_text) Error.map_error : (Error -> Error) -> Any Error.map_error f = this.catch (x -> Error.throw (f x)) -## Checks if the underlying value is an error. +## Checks if `this` is an error. + + > Example + Checking if the value 1 is an error. + 1.is_error Error.is_error : Boolean Error.is_error = True -## Takes any value, and if it is a dataflow error, throws it as a Panic. - Otherwise, returns the original value unchanged. +## Takes any value, and if it is a dataflow error, throws it as a Panic, + otherwise, returns the original value unchanged. + + Arguments: + - value: The value to rethrow any errors on as a panic. + + > Example + Rethrowing a dataflow error as a panic. + Panic.rethrow (Error.throw "Oh, no!") Panic.rethrow : (Any ! Any) -> Any Panic.rethrow value = value.catch Panic.throw + diff --git a/distribution/std-lib/Standard/src/Base/Math.enso b/distribution/std-lib/Standard/src/Base/Math.enso index d4e58275a1..248cd8b9b9 100644 --- a/distribution/std-lib/Standard/src/Base/Math.enso +++ b/distribution/std-lib/Standard/src/Base/Math.enso @@ -18,9 +18,35 @@ e : Decimal e = 2.718281828459045235360 ## Returns the smaller value of `a` and `b`. + + Arguments: + - a: The first number. + - b: The second number. + + ? Math.min or Number.min + While we provide the min method on `Number`, we find it more intuitive to + write `Math.min a b` rather than `a.min b`. To that end, we recommend using + the first style. + + > Example + Calculate the smallest number out of 1 and 2. + Math.min 1 2 min : Number -> Number -> Number min a b = if a <= b then a else b ## Returns the larger value of `a` and `b`. + + Arguments: + - a: The first number. + - b: The second number. + + ? Math.max or Number.max + While we provide the max method on `Number`, we find it more intuitive to + write `Math.max a b` rather than `a.max b`. To that end, we recommend using + the first style. + + > Example + Calculate the largest number out of 1 and 2. + Math.max 1 2 max : Number -> Number -> Number max a b = if a < b then b else a diff --git a/distribution/std-lib/Standard/src/Base/Meta.enso b/distribution/std-lib/Standard/src/Base/Meta.enso index 38c25d9eb1..54ea61ceb2 100644 --- a/distribution/std-lib/Standard/src/Base/Meta.enso +++ b/distribution/std-lib/Standard/src/Base/Meta.enso @@ -2,91 +2,80 @@ from Standard.Base import all import Builtins -## Represents a polyglot language. -type Language - ## The Java laguage. - type Java - ## Unknown language. - type Unknown +## UNSTABLE + ADVANCED -## A meta-representation of a runtime value. + Returns a meta-representation of a given runtime entity. - ! Warning - The functionality contained in this module exposes certain implementation - details of the language. As such, the API has no stability guarantees and - is subject to change as the Enso interpreter evolves. -type Meta - ## An Atom meta-representation. - type Atom value - ## A constructor meta-representation. - type Constructor value - ## A primitive value meta-prepresentation. - type Primitive value - ## An unresolved symbol meta-representation. - type Unresolved_Symbol value - ## An error meta-representation, containing the payload of a dataflow error. - type Error value - ## A polyglot value meta-representation. - type Polyglot value + Arguments: + - value: The runtime entity to get the meta representation of. +meta : Any -> Meta +meta value = if Builtins.Meta.is_atom value then Atom value else + if Builtins.Meta.is_constructor value then Constructor value else + if Builtins.Meta.is_polyglot value then Polyglot value else + if Builtins.Meta.is_unresolved_symbol value then Unresolved_Symbol value else + if Builtins.Meta.is_error value then Error value.catch else + Primitive value -## Returns a vector of field values of the given atom. -Atom.fields : Vector.Vector -Atom.fields = Vector.Vector (Builtins.Meta.get_atom_fields this.value) +## UNSTABLE + ADVANCED -## Returns a constructor value of the given atom. -Atom.constructor : Any -Atom.constructor = Builtins.Meta.get_atom_constructor this.value + Checks whether two objects are represented by the same underlying reference. -## Returns a new unresolved symbol with its name changed to the provided - argument. -Unresolved_Symbol.rename : Text -> Any -Unresolved_Symbol.rename new_name = - Builtins.Meta.create_unresolved_symbol new_name this.scope + Arguments: + - value_1: The first value. + - value_2: The second value. +is_same_object : Any -> Any -> Boolean +is_same_object value_1 value_2 = Builtins.Meta.is_same_object value_1 value_2 -## Returns the name of an unresolved symbol. -Unresolved_Symbol.name : Text -Unresolved_Symbol.name = Builtins.Meta.get_unresolved_symbol_name this.value +## UNSTABLE + ADVANCED -## Returns the definition scope of an unresolved symbol. -Unresolved_Symbol.scope : Any -Unresolved_Symbol.scope = Builtins.Meta.get_unresolved_symbol_scope this.value + Checks if `this` is an instance of `typ`. -## Returns a vector of field names defined by a constructor. -Constructor.fields : Vector.Vector -Constructor.fields = Vector.Vector (Builtins.Meta.get_constructor_fields this.value) - -## Returns the name of a constructor. -Constructor.name : Text -Constructor.name = Builtins.Meta.get_constructor_name this.value - -## Creates a new atom of the given constructor, with field values provided - in the `fields` vector. -Constructor.new : Vector.Vector -> Any -Constructor.new fields = Builtins.Meta.new_atom this.value fields.to_array - -## Returns the language of a polyglot value. -Polyglot.get_language : Language -Polyglot.get_language = - lang_str = Builtins.Meta.get_polyglot_language - if lang_str == "java" then Java else Unknown - -## Checks if `this` is an instance of `typ`. + Arguments: + - typ: The type to check `this` against. Any.is_a : Any -> Boolean Any.is_a typ = here.is_a this typ -## Checks if `this` is an instance of `typ`. +## UNSTABLE + ADVANCED + + Checks if `this` is an instance of `typ`. + + Arguments: + - typ: The type to check `this` against. Any.is_an : Any -> Boolean Any.is_an typ = here.is_a this typ -## Checks if `this` is an instance of `typ`. +## UNSTABLE + ADVANCED + + Checks if `this` is an instance of `typ`. + + Arguments: + - typ: The type to check `this` against. Base.Error.is_a : Any -> Boolean Base.Error.is_a typ = this.is_an typ -## Checks if `this` is an instance of `typ`. +## UNSTABLE + ADVANCED + + Checks if `this` is an instance of `typ`. + + Arguments: + - typ: The type to check `this` against. Base.Error.is_an : Any -> Boolean Base.Error.is_an typ = typ == Base.Error -## Checks if `value` is an instance of `typ`. +## UNSTABLE + ADVANCED + + Checks if `value` is an instance of `typ`. + + Arguments: + - value: The value to check for being an instance of `typ`. + - typ: The type to check `this` against. is_a : Any -> Any -> Boolean is_a value typ = if typ == Any then True else if Builtins.Meta.is_error value then typ == Base.Error else @@ -113,23 +102,170 @@ is_a value typ = if typ == Any then True else Unresolved_Symbol _ -> typ == Unresolved_Symbol _ -> False -## Checks if `value` is an instance of `typ`. +## UNSTABLE + ADVANCED + + Checks if `value` is an instance of `typ`. + + Arguments: + - value: The value to check for being an instance of `typ`. + - typ: The type to check `this` against. is_an : Any -> Any -> Boolean is_an value typ = here.is_a value typ -## Returns a meta-representation of a given runtime entity. -meta : Any -> Meta -meta value = if Builtins.Meta.is_atom value then Atom value else - if Builtins.Meta.is_constructor value then Constructor value else - if Builtins.Meta.is_polyglot value then Polyglot value else - if Builtins.Meta.is_unresolved_symbol value then Unresolved_Symbol value else - if Builtins.Meta.is_error value then Error value.catch else - Primitive value +## Represents a polyglot language. +type Language -## Checks whether two objects are represented by the same underlying reference. - This is a power-user feature, that is only useful for certain optimizations. -is_same_object : Any -> Any -> Boolean -is_same_object value_1 value_2 = Builtins.Meta.is_same_object value_1 value_2 + ## UNSTABLE + ADVANCED + + The Java laguage. + type Java + + ## UNSTABLE + ADVANCED + + An unknown language. + type Unknown + +## UNSTABLE + ADVANCED + + A meta-representation of a runtime value. + + ! Warning + The functionality contained in this module exposes certain implementation + details of the language. As such, the API has no stability guarantees and + is subject to change as the Enso interpreter evolves. +type Meta + + ## UNSTABLE + ADVANCED + + An Atom meta-representation. + + Arguments: + - value: The value of the atom in the meta representation. + type Atom value + + ## UNSTABLE + ADVANCED + + A constructor meta-representation. + + Arguments: + - value: The value of the constructor in the meta representation. + type Constructor value + + ## UNSTABLE + ADVANCED + + A primitive value meta-prepresentation. + + Arguments: + - value: The value of the primitive object in the meta representation. + type Primitive value + + ## UNSTABLE + ADVANCED + + An unresolved symbol meta-representation. + + Arguments: + - value: The value of the unresolved symbol in the meta representation. + type Unresolved_Symbol value + + ## UNSTABLE + ADVANCED + + An error meta-representation, containing the payload of a dataflow error. + + Arguments: + - value: The payload of the error. + type Error value + + ## UNSTABLE + ADVANCED + + A polyglot value meta-representation. + + Arguments: + - value: The polyglot value contained in the meta representation. + type Polyglot value + +## UNSTABLE + ADVANCED + + Returns a vector of field values of the given atom. +Atom.fields : Vector.Vector +Atom.fields = Vector.Vector (Builtins.Meta.get_atom_fields this.value) + +## UNSTABLE + ADVANCED + + Returns a constructor value of the given atom. +Atom.constructor : Any +Atom.constructor = Builtins.Meta.get_atom_constructor this.value + +## UNSTABLE + ADVANCED + + Returns a new unresolved symbol with its name changed to the provided + argument. + + Arguments: + - new_name: The new name for the unresolved symbol. +Unresolved_Symbol.rename : Text -> Any +Unresolved_Symbol.rename new_name = + Builtins.Meta.create_unresolved_symbol new_name this.scope + +## UNSTABLE + ADVANCED + + Returns the name of an unresolved symbol. +Unresolved_Symbol.name : Text +Unresolved_Symbol.name = Builtins.Meta.get_unresolved_symbol_name this.value + +## UNSTABLE + ADVANCED + + Returns the definition scope of an unresolved symbol. +Unresolved_Symbol.scope : Any +Unresolved_Symbol.scope = Builtins.Meta.get_unresolved_symbol_scope this.value + +## UNSTABLE + ADVANCED + + Returns a vector of field names defined by a constructor. +Constructor.fields : Vector.Vector +Constructor.fields = Vector.Vector (Builtins.Meta.get_constructor_fields this.value) + +## UNSTABLE + ADVANCED + + Returns the name of a constructor. +Constructor.name : Text +Constructor.name = Builtins.Meta.get_constructor_name this.value + +## UNSTABLE + ADVANCED + + Creates a new atom of the given constructor. + + Arguments: + - fields: A vector of arguments to pass to the constructor when creating the + new atom. +Constructor.new : Vector.Vector -> Any +Constructor.new fields = Builtins.Meta.new_atom this.value fields.to_array + +## UNSTABLE + ADVANCED + + Returns the language with which a polyglot value is associated. +Polyglot.get_language : Language +Polyglot.get_language = + lang_str = Builtins.Meta.get_polyglot_language + if lang_str == "java" then Java else Unknown ## PRIVATE diff --git a/distribution/std-lib/Standard/src/Base/Meta/Enso_Project.enso b/distribution/std-lib/Standard/src/Base/Meta/Enso_Project.enso index 5ce6ee3ce1..29844e3c9a 100644 --- a/distribution/std-lib/Standard/src/Base/Meta/Enso_Project.enso +++ b/distribution/std-lib/Standard/src/Base/Meta/Enso_Project.enso @@ -3,9 +3,17 @@ from Standard.Base import all import Builtins ## Returns the root directory of the project. + + > Example + Get the root directory of the current project. + Enso_Project.root Builtins.Project_Description.root : File.File Builtins.Project_Description.root = File.File this.prim_root_file ## Returns the root data directory of the project. + + > Example + Get the data directory of the current project. + Enso_Project.data Builtins.Project_Description.data : File.File Builtins.Project_Description.data = this.root / "data" diff --git a/distribution/std-lib/Standard/src/Base/Network/Http.enso b/distribution/std-lib/Standard/src/Base/Network/Http.enso index e9bc1d6526..42b45a7d3e 100644 --- a/distribution/std-lib/Standard/src/Base/Network/Http.enso +++ b/distribution/std-lib/Standard/src/Base/Network/Http.enso @@ -24,18 +24,180 @@ polyglot java import java.net.URI polyglot java import java.time.Duration as Java_Duration polyglot java import org.enso.base.Http_Utils -## An error when sending an Http request. +## UNSTABLE + + An error when sending an Http request. + + Arguments: + - message: The message for the error. type Request_Error message +## UNSTABLE + + Convert a request error to a human-readable form. Request_Error.to_display_text = "Error when sending request: " + this.message +## Create a new instance of the HTTP client. + + Arguments: + - timeout: The length of time the client will wait for responses. + - follow_redirects: Whether or not the client should follow redirects. + - proxy: The proxy that the client should use, if any. + - version: The HTTP version supported by the client. + + > Example + Create an HTTP client with default settings. + Http.new + + > Example + Create an HTTP client with extended timeout. + Http.new timeout=30.seconds + + > Example + Create an HTTP client with extended timeout and proxy settings. + Http.new (timeout = 30.seconds) (proxy = Proxy.new "example.com" 8080) +new : Duration -> Boolean -> Proxy -> Http +new (timeout = 10.seconds) (follow_redirects = True) (proxy = Proxy.System) (version = Version.Http_1_1) = + Http timeout follow_redirects proxy version + +## Send an Options request. + + Arguments: + - uri: The address to which the request will be sent. + - headers: Any headers for the options request. + + > Example + Send an Options request. + Http.options "http://httpbin.org" +options : (Text | Uri) -> Vector.Vector -> Response ! Request_Error +options uri (headers = []) = here.new.options uri headers + +## Send a Get request. + + Arguments: + - uri: The address to which the request will be sent. + - headers: Any headers for the options request. + + > Example + Send a Get request. + Http.get "http://httpbin.org/get" + + > Example + Send authenticated Get request (note the use of TLS). + Http.get "https://httpbin.org/basic-auth/user/pass" [Header.authorization_basic "user" "pass"] + + > Example + Download a file. + out_file = File.new "/tmp/out.bin" + res = Http.get "http://httpbin.org/bytes/1024" + res.body.to_file out_file +get : (Text | Uri) -> Vector.Vector -> Response ! Request_Error +get uri (headers = []) = here.new.get uri headers + +## Send the Get request and return the body. + + Arguments: + - uri: The address to which the request will be sent. + - headers: Any headers for the options request. + + > Example + Send a Get request. + Http.fetch "http://httpbin.org/get" + + > Example + Send authenticated Get request (note the use of TLS). + Http.fetch "https://httpbin.org/basic-auth/user/pass" [Header.authorization_basic "user" "pass"] + + > Example + Download a file. + out_file = File.new "/tmp/out.bin" + res = Http.fetch "http://httpbin.org/bytes/1024" . to_file out_file +fetch : (Text | Uri) -> Vector.Vector -> Response ! Request_Error +fetch uri (headers = []) = + here.new.get uri headers . body + +## Send a Head request. + + Arguments: + - uri: The address to which the request will be sent. + - headers: Any headers for the options request. + + > Example + Send a Head request. + res = Http.head "http://httpbin.org" + IO.println res.headers +head : (Text | Uri) -> Vector.Vector -> Response ! Request_Error +head uri (headers = []) = here.new.options uri headers + +## Send a Post request. + + Arguments: + - uri: The address to which the request will be sent. + - body: The contents of the post request. + - headers: Any headers for the options request. + + > Example + Send a Post request with binary data. + body = Body.Bytes "Hello".utf_8 + header_binary = Header.content_type "application/octet-stream" + Http.post "http://httpbin.org/post" body [header_binary] +post : (Text | Uri) -> Request_Body -> Vector.Vector -> Respoonse ! Request_Error +post uri body (headers = []) = here.new.post uri body headers + +## Send a Post request with the form. By default it will be encoded as + "application/x-www-form-urlencoded". To encode the form as + "multipart/form-data" add the appropriate header. + + Arguments: + - uri: The address to which the request will be sent. + - parts: A form, or a vector of parts for creating a form. + - headers: Any headers for the options request. + + > Example + Send a Post request with form. + form = [Form.text_field "name" "John Doe", Form.file_field "license.txt" (Enso_Project.root / "LICENSE")] + Http.post_form "http://httpbin.org/post" form + + > Example + Send a Post request with form encoded as "multipart/form-data". + form = [Form.text_field "name" "John Doe", Form.file_field "license.txt" (Enso_Project.root / "LICENSE")] + Http.post_form "http://httpbin.org/post" form [Header.multipart_form_data] +post_form : (Text | Uri) -> (Vector | Form) -> Vector.Vector -> Response ! Request_Error +post_form uri parts (headers = []) = here.new.post_form uri parts headers + +## Send a Post request with body with content-type "application/json". + + Arguments: + - uri: The address to which the request will be sent. + - body_json: The json for the body. + - headers: Any headers for the options request. + + > Example + Send a Post request with json data. + json = Json.parse <| ''' + {"key":"val"} + Http.post_json "http://httpbin.org/post" json +post_json : (Text | Uri) -> Json -> Vector.Vector -> Response ! Request_Error +post_json uri body_json (headers = []) = here.new.post_json uri body_json headers + type Http + ## An HTTP client. + + Arguments: + - timeout: The length of time the client will wait for responses. + - follow_redirects: Whether or not the client should follow redirects. + - proxy: The proxy that the client should use, if any. + - version: The HTTP version supported by the client. type Http timeout follow_redirects proxy version ## Send an Options request. + Arguments: + - uri: The address to which the request will be sent. + - headers: Any headers for the options request. + > Example Send an Options request. Http.new.options "http://httpbin.org" @@ -46,6 +208,10 @@ type Http ## Send a Get request. + Arguments: + - uri: The address to which the request will be sent. + - headers: Any headers for the options request. + > Example Send a Get request. Http.new.get "http://httpbin.org/get" @@ -66,6 +232,10 @@ type Http ## Send a Head request. + Arguments: + - uri: The address to which the request will be sent. + - headers: Any headers for the options request. + > Example Send a Head request. res = Http.new.head "http://httpbin.org" @@ -77,6 +247,11 @@ type Http ## Send a Post request. + Arguments: + - uri: The address to which the request will be sent. + - body: The body of the post request. + - headers: Any headers for the options request. + > Example Send a Post request with binary data. body = Body.Bytes "Hello".utf_8 @@ -91,6 +266,11 @@ type Http "application/x-www-form-urlencoded". To encode the form as "multipart/form-data" add the appropriate header. + Arguments: + - uri: The address to which the request will be sent. + - parts: A form, or the parts for creating a form. + - headers: Any headers for the options request. + > Example Send a Post request with form. form = [Form.text_field "name" "John Doe", Form.file_field "license.txt" (Enso_Project.root / "LICENSE")] @@ -114,6 +294,11 @@ type Http ## Send a Post request with body with content-type "application/json". + Arguments: + - uri: The address to which the request will be sent. + - body_json: The JSON body for the post request. + - headers: Any headers for the options request. + > Example Send a Post request with json data. json = Json.parse <| ''' @@ -127,6 +312,11 @@ type Http ## Send a Put request. + Arguments: + - uri: The address to which the request will be sent. + - body: The body for the put request. + - headers: Any headers for the options request. + > Example Send a Put request with binary data. body = Body.Bytes "contents".utf_8 @@ -139,6 +329,11 @@ type Http ## Send a Put request with body with content-type "application/json". + Arguments: + - uri: The address to which the request will be sent. + - body_json: The JSON for the body of the put request. + - headers: Any headers for the options request. + > Example Send a Put request with json data. json = Json.parse <| ''' @@ -152,6 +347,10 @@ type Http ## Create a Delete request. + Arguments: + - uri: The address to which the request will be sent. + - headers: Any headers for the options request. + > Example Send a Delete request. Http.new.delete "http://httpbin.org/delete" @@ -162,6 +361,9 @@ type Http ## Create a request + Arguments: + - req: The HTTP request to send using `this` HTTP client. + > Example Send a Get request with headers. req = Request.new Method.Get "http://httpbin.org/get" . with_header "X-Trace-Id" "00000" @@ -282,109 +484,3 @@ type Http builder.version HttpClient.Version.HTTP_2 # build http client builder.build - -## Create a new instance of HTTP client. - - > Example - Create an HTTP client with default settings. - Http.new - - > Example - Create an HTTP client with extended timeout. - Http.new timeout=30.seconds - - > Example - Create an HTTP client with extended timeout and proxy settings. - Http.new (timeout = 30.seconds) (proxy = Proxy.new "example.com" 8080) -new : Duration -> Boolean -> Proxy -> Http -new (timeout = 10.seconds) (follow_redirects = True) (proxy = Proxy.System) (version = Version.Http_1_1) = - Http timeout follow_redirects proxy version - -## Send an Options request. - - > Example - Send an Options request. - Http.options "http://httpbin.org" -options : (Text | Uri) -> Vector.Vector -> Response ! Request_Error -options uri (headers = []) = here.new.options uri headers - -## Send a Get request. - - > Example - Send a Get request. - Http.get "http://httpbin.org/get" - - > Example - Send authenticated Get request (note the use of TLS). - Http.get "https://httpbin.org/basic-auth/user/pass" [Header.authorization_basic "user" "pass"] - - > Example - Download a file. - out_file = File.new "/tmp/out.bin" - res = Http.get "http://httpbin.org/bytes/1024" - res.body.to_file out_file -get : (Text | Uri) -> Vector.Vector -> Response ! Request_Error -get uri (headers = []) = here.new.get uri headers - -## Send the Get request and return the body. - - > Example - Send a Get request. - Http.fetch "http://httpbin.org/get" - - > Example - Send authenticated Get request (note the use of TLS). - Http.fetch "https://httpbin.org/basic-auth/user/pass" [Header.authorization_basic "user" "pass"] - - > Example - Download a file. - out_file = File.new "/tmp/out.bin" - res = Http.fetch "http://httpbin.org/bytes/1024" . to_file out_file -fetch : (Text | Uri) -> Vector.Vector -> Response ! Request_Error -fetch uri (headers = []) = - here.new.get uri headers . body - -## Send a Head request. - - > Example - Send a Head request. - res = Http.head "http://httpbin.org" - IO.println res.headers -head : (Text | Uri) -> Vector.Vector -> Response ! Request_Error -head uri (headers = []) = here.new.options uri headers - -## Send a Post request. - - > Example - Send a Post request with binary data. - body = Body.Bytes "Hello".utf_8 - header_binary = Header.content_type "application/octet-stream" - Http.post "http://httpbin.org/post" body [header_binary] -post : (Text | Uri) -> Request_Body -> Vector.Vector -> Respoonse ! Request_Error -post uri body (headers = []) = here.new.post uri body headers - -## Send a Post request with the form. By default it will be encoded as - "application/x-www-form-urlencoded". To encode the form as - "multipart/form-data" add the appropriate header. - - > Example - Send a Post request with form. - form = [Form.text_field "name" "John Doe", Form.file_field "license.txt" (Enso_Project.root / "LICENSE")] - Http.post_form "http://httpbin.org/post" form - - > Example - Send a Post request with form encoded as "multipart/form-data". - form = [Form.text_field "name" "John Doe", Form.file_field "license.txt" (Enso_Project.root / "LICENSE")] - Http.post_form "http://httpbin.org/post" form [Header.multipart_form_data] -post_form : (Text | Uri) -> (Vector | Form) -> Vector.Vector -> Response ! Request_Error -post_form uri parts (headers = []) = here.new.post_form uri parts headers - -## Send a Post request with body with content-type "application/json". - - > Example - Send a Post request with json data. - json = Json.parse <| ''' - {"key":"val"} - Http.post_json "http://httpbin.org/post" json -post_json : (Text | Uri) -> Json -> Vector.Vector -> Response ! Request_Error -post_json uri body_json (headers = []) = here.new.post_json uri body_json headers diff --git a/distribution/std-lib/Standard/src/Base/Network/Http/Form.enso b/distribution/std-lib/Standard/src/Base/Network/Http/Form.enso index c7a24dfa39..ca0c8d0970 100644 --- a/distribution/std-lib/Standard/src/Base/Network/Http/Form.enso +++ b/distribution/std-lib/Standard/src/Base/Network/Http/Form.enso @@ -5,9 +5,19 @@ import Standard.Base.Data.Vector ## The HTTP form containing a vector of parts. type Form + ## PRIVATE + + A type representing form data. + + Arguments: + - parts: A vector of form segments. type Form parts ## Convert this to a Form. + + > Example + Convert to a form. + Form.new [Part "foo" (Part_Text "bar")] . to_form to_form : Form to_form = this @@ -17,25 +27,62 @@ Vector.Vector.to_form = Form this ## The key-value element of the form. type Part + ## A form part. + + Arguments: + - key: The key for the form section. + - value: The value of the form section. type Part key value ## The value of the form element. type Part_Value + ## A textual value for a form part. + + Arguments: + - part_text: The text for the form part. type Part_Text part_text + ## A file value for a form part. + + Arguments: + - part_file: The file for the form part. type Part_File part_file ## Create Form data from Parts. + + Arguments: + - parts: A vector of parts to make up the form. + + > Example + Create a new form + Form.new (Form.text_field "foo" "bar") new : Vector.Vector -> Form new parts = Form parts # Helpers for creating different parts of the form. ## Create a text field of a Form. + + Arguments: + - key: The key for the field in the form. + - val: The text for the textual field. + + > Example + Create a textual form field. + Form.text_field "Foo" "bar" text_field : Text -> Text -> Part text_field key val = Part key (Part_Text val) ## Create a file field of a Form. + + Arguments: + - key: The key for the field in the form. + - file: The textual file contents. + + > Example + Create a file form field. + Form.file_field "Foo" "My file contents" file_field : Text -> Text -> Part file_field key file = Part key (Part_File file) + diff --git a/distribution/std-lib/Standard/src/Base/Network/Http/Header.enso b/distribution/std-lib/Standard/src/Base/Network/Http/Header.enso index d074de2cdf..b801a45172 100644 --- a/distribution/std-lib/Standard/src/Base/Network/Http/Header.enso +++ b/distribution/std-lib/Standard/src/Base/Network/Http/Header.enso @@ -4,34 +4,78 @@ polyglot java import org.enso.base.Http_Utils type Header + ## PRIVATE + + A type representing a header. + + Arguments: + - name: The header name. + - value: The header value. type Header name value ## Header equality. + + Arguments: + - that: The header to compare against. + + > Example + Compare two headers. + (Header.new "My_Header" "foo") == (Header.new "My_Header" "bar") == : Header -> Boolean == that = (this.name.equals_ignore_case that.name) && this.value==that.value ## Create a new Header. + + Arguments: + - name: The name of the header. + - value: The value for the header. + + > Example + Create a new header called "My_Header". + Header.new "My_Header" "my header's value" new : Text -> Text -> Header new name value = Header name value # Accept -## Create "Accept" header. +## Create an "Accept" header. + + Arguments: + - value: The value for the accept header. + + > Example + Create an accept header. + Header.accept "my_field" accept : Text -> Header accept value = Header "Accept" value -## Header "Accept: */*". +## Create a header that accepts all (`"*/*"`). + + > Example + Create an accept all header. + Header.accept_all accept_all : Header accept_all = here.accept "*/*" # Authorization ## Create "Authorization" header. + + Arguments: + - value: The value for the authorization header. + + > Example + Create an auth header containing "foo". + Header.authorization "foo" authorization : Text -> Header authorization value = Header "Authorization" value ## Create HTTP basic auth header. + Arguments: + - user: The username. + - pass: The password. + > Example Create basic auth header. Header.authorization_basic "user" "pass" @@ -42,27 +86,57 @@ authorization_basic user pass = # Content-Type ## Create "Content-Type" header. + + Arguments: + - value: The value for the content type header. + + > Example + Create a content type header containing "my_type". + Header.content_type "my_type" content_type : Text -> Header content_type value = Header "Content-Type" value ## Header "Content-Type: application/json". + + > Example + Create a header with content type "application/json". + Header.application_json application_json : Header application_json = here.content_type "application/json" ## Header "Content-Type: application/octet-stream". + + > Example + Create a header with content type "application/octet-stream". + Header.application_octet_stream application_octet_stream : Header application_octet_stream = here.content_type "application/octet-stream" ## Header "Content-Type: application/x-www-form-urlencoded". + + > Example + Create a header with content type "application/x-www-form-urlencoded". + Header.application_x_www_form_urlencoded application_x_www_form_urlencoded : Header application_x_www_form_urlencoded = here.content_type "application/x-www-form-urlencoded" ## Header "Content-Type: multipart/form-data". + + Arguments: + - boundary: The text that delimits boundaries between the parts of the form. + + > Example + Create a header with content type "multipart/form-data". + Header.multipart_form_data multipart_form_data : Text -> Header multipart_form_data (boundary = "") = if boundary == "" then here.content_type "multipart/form-data" else here.content_type ("multipart/form-data; boundary=" + boundary) ## Header "Content-Type: text/plain". + + > Example + Create a header with the content type "text/plain". + Header.text_plain text_plain : Header text_plain = here.content_type "text/plain" diff --git a/distribution/std-lib/Standard/src/Base/Network/Http/Method.enso b/distribution/std-lib/Standard/src/Base/Network/Http/Method.enso index 71fc31670c..9e9cc24e03 100644 --- a/distribution/std-lib/Standard/src/Base/Network/Http/Method.enso +++ b/distribution/std-lib/Standard/src/Base/Network/Http/Method.enso @@ -1,10 +1,25 @@ type Method + ## The HTTP method "OPTIONS". type Options + + ## The HTTP method "GET". type Get + + ## The HTTP method "HEAD". type Head + + ## The HTTP method "POST". type Post + + ## The HTTP method "PUT". type Put + + ## The HTTP method "DELETE". type Delete + + ## The HTTP method "TRACE". type Trace + + ## The HTTP method "CONNECT". type Connect diff --git a/distribution/std-lib/Standard/src/Base/Network/Http/Request.enso b/distribution/std-lib/Standard/src/Base/Network/Http/Request.enso index 99d5912d32..0b9d7e9eb2 100644 --- a/distribution/std-lib/Standard/src/Base/Network/Http/Request.enso +++ b/distribution/std-lib/Standard/src/Base/Network/Http/Request.enso @@ -10,11 +10,115 @@ import Standard.Base.System.File polyglot java import org.enso.base.Text_Utils +## Create new HTTP request. + + Arguments: + - method: The HTTP method represented by the request. + - addr: The address for the request. + - headers: A vector containing headers for the request. + - body: The body of the request. + + > Example + Create a new post request with no headers and no body. + Request.new Method.Post (Uri.parse "http://example.com") +new : Method -> (Text | Uri) -> Vector.Vector -> Request_Body -> Request +new method addr (headers = []) (body = Request_Body.Empty) = + Panic.recover (Request method (Internal.panic_on_error (addr.to_uri)) headers body) . catch Internal.recover_panic + +## Create an Options request. + + Arguments: + + > Example + Create a new options request. + Request.options (Uri.parse "http://example.com") +options : (Text | Uri) -> Vector.Vector -> Request +options addr (headers = []) = here.new Method.Options addr headers + +## Create a Get request. + + Arguments: + - addr: The address for the request. + - headers: A vector containing headers for the request. + + > Example + Create a new get request. + Request.get (Uri.parse "http://example.com") +get : (Text | Uri) -> Vector.Vector -> Request +get addr (headers = []) = here.new Method.Get addr headers + +## Create a Head request. + + Arguments: + - addr: The address for the request. + - headers: A vector containing headers for the request. + + > Example + Create a new head request. + Request.head (Uri.parse "http://example.com") +head : (Text | Uri) -> Vector.Vector -> Request +head addr (headers = []) = here.new Method.Head addr headers + +## Create a Post request. + + Arguments: + - addr: The address for the request. + - body: The body for the request. + - headers: A vector containing headers for the request. + + > Example + Create a new post request. + Request.post (Uri.parse "http://example.com") Request_Body.Empty +post : (Text | Uri) -> Request_Body -> Vector.Vector -> Request +post addr body (headers = []) = here.new Method.Post addr headers body + +## Create a Put request. + + Arguments: + - addr: The address for the request. + - body: The body for the request. + - headers: A vector containing headers for the request. + + > Example + Create a new put request. + Request.put (Uri.parse "http://example.com") Request_Body.Empty +put : (Text | Uri) -> Request_Body -> Vector.Vector -> Request +put addr body (headers = []) = here.new Method.Put addr headers body + +## Create a Delete request. + + Arguments: + - addr: The address for the request. + - headers: A vector containing headers for the request. + + > Example + Create a new delete request. + Request.delete (Uri.parse "http://example.com") +delete : (Text | Uri) -> Vector.Vector -> Request +delete addr (headers = []) = here.new Method.Delete addr headers + type Request + ## PRIVATE + + A type representing an HTTP request. + + Arguments: + - method: The HTTP method represented by the request. + - uri: The URI for the request. + - headers: A vector containing headers for the request. + - body: The body of the request. type Request method uri headers body - ## Set header. + ## Sets the header for the request. + + Arguments: + - key: The name for the header in this request. + - val: The value for the header in this request. + + > Example + Create a request and add a new header to it. + Request.delete.with_header "Foo" "bar" with_header : Text -> Text -> Request with_header key val = new_header = Header.new key val @@ -27,54 +131,54 @@ type Request Pair acc False -> acc + [new_header] Request this.method this.uri new_headers this.body - ## Set headers. + ## Sets the headers in the request. + + Arguments: + - new_headers: A vector of headers to put in the request. If `this` has + any headers they will be replaced with new_headers. + + > Example + Create a request and unset all the headers. + Request.delete.with_headers [] with_headers : [Header] -> Request with_headers new_headers = update_header req new_header = req.with_header new_header.name new_header.value new_headers.fold this update_header - ## Set body. + ## Set the body for the request. + + Arguments: + - new_body: The body to insert into the request. + + > Example + Unsetting the body in a post request. + Request.post (Uri.parse "http://example.com") Request_Body.Empty |> .with_body Request_Body.Empty with_body : Request_Body -> Request with_body new_body = Request this.method this.uri this.headers new_body - ## Set body encoded as "application/json". + ## Set the body text in the request encoded as "application/json". + + Arguments: + - json_body: The body to insert into the request. It must be textual + JSON. + + > Example + Setting the body in a post request to some JSON. + Request.post (Uri.parse "http://example.com") Request_Body.Empty |> .with_body "{ "a": "b" }" with_json : Text -> Request with_json json_body = new_body = Request_Body.Json json_body Request this.method this.uri this.headers new_body . with_headers [Header.application_json] - ## Set body as vector of parts encoded as - "application/x-www-form-urlencoded". + ## Set body as vector of parts encoded as "application/x-www-form-urlencoded". + + Arguments: + - parts: The parts of the form, or a form itself. + + > Example + Create a delete request with an empty form. + Request.delete (Uri.parse "http://example.com") . with_form [] with_form : (Vector | Form) -> Request with_form parts = new_body = Request_Body.Form parts.to_form Request this.method this.uri this.headers new_body . with_headers [Header.application_x_www_form_urlencoded] - -## Create new HTTP request. -new : Method -> (Text | Uri) -> Vector.Vector -> Request_Body -> Request -new method addr (headers = []) (body = Request_Body.Empty) = - Panic.recover (Request method (Internal.panic_on_error (addr.to_uri)) headers body) . catch Internal.recover_panic - -## Create an Options request. -options : (Text | Uri) -> Vector.Vector -> Request -options addr (headers = []) = here.new Method.Options addr headers - -## Create a Get request. -get : (Text | Uri) -> Vector.Vector -> Request -get addr (headers = []) = here.new Method.Get addr headers - -## Create a Head request. -head : (Text | Uri) -> Vector.Vector -> Request -head addr (headers = []) = here.new Method.Head addr headers - -## Create a Post request. -post : (Text | Uri) -> Request_Body -> Vector.Vector -> Request -post addr body (headers = []) = here.new Method.Post addr headers body - -## Create a Put request. -put : (Text | Uri) -> Request_Body -> Vector.Vector -> Request -put addr body (headers = []) = here.new Method.Put addr headers body - -## Create a Delete request. -delete : (Text | Uri) -> Vector.Vector -> Request -delete addr (headers = []) = here.new Method.Delete addr headers diff --git a/distribution/std-lib/Standard/src/Base/Network/Http/Request/Body.enso b/distribution/std-lib/Standard/src/Base/Network/Http/Request/Body.enso index 76bd2d2456..d093a6ae86 100644 --- a/distribution/std-lib/Standard/src/Base/Network/Http/Request/Body.enso +++ b/distribution/std-lib/Standard/src/Base/Network/Http/Request/Body.enso @@ -7,16 +7,31 @@ type Body type Empty ## Request body with text. + + Arguments: + - text: The plain text in the request body. type Text text ## Request body with JSON. + + Arguments: + - json: The JSON in the request body. type Json json ## Request body with form data. + + Arguments: + - form: The form data in the request body. type Form form ## Request body with file data. + + Arguments: + - file: The file data in the request body. type File file ## Request body with binary. + + Arguments: + - bytes: The binary data in the request body. type Bytes bytes diff --git a/distribution/std-lib/Standard/src/Base/Network/Http/Response.enso b/distribution/std-lib/Standard/src/Base/Network/Http/Response.enso index 60ce36115a..c37f79d456 100644 --- a/distribution/std-lib/Standard/src/Base/Network/Http/Response.enso +++ b/distribution/std-lib/Standard/src/Base/Network/Http/Response.enso @@ -9,6 +9,13 @@ polyglot java import org.enso.base.Http_Utils type Response + ## PRIVATE + + A type representing an HTTP response. + + Arguments: + - internal_http_response: The internal represnetation of the HTTP + response. type Response internal_http_response ## Get the response headers. @@ -25,6 +32,6 @@ type Response code : Status_Code code = Status_Code.status_code this.internal_http_response.statusCode - ## A Response to Json conversion. + ## Convert the response to JSON. to_json : Json.Object to_json = Json.from_pairs [["type", "Response"], ["headers", this.headers], ["body", this.body], ["code", this.code]] diff --git a/distribution/std-lib/Standard/src/Base/Network/Http/Response/Body.enso b/distribution/std-lib/Standard/src/Base/Network/Http/Response/Body.enso index 7f920331e7..acf75f35a3 100644 --- a/distribution/std-lib/Standard/src/Base/Network/Http/Response/Body.enso +++ b/distribution/std-lib/Standard/src/Base/Network/Http/Response/Body.enso @@ -6,6 +6,9 @@ import Standard.Base.System.File type Body ## Response body + + Arguments: + - bytes: The body of the response as binary data. type Body bytes ## Convert response body to Text. @@ -17,7 +20,10 @@ type Body to_json = Json.parse this.to_text ## Write response body to a File. + + Arguments: + - file: The file to write the bytes to. to_file : File -> File - to_file path = - path.write_bytes this.bytes - path + to_file file = + file.write_bytes this.bytes + file diff --git a/distribution/std-lib/Standard/src/Base/Network/Http/Status_Code.enso b/distribution/std-lib/Standard/src/Base/Network/Http/Status_Code.enso index 2ab6092bfa..acba877422 100644 --- a/distribution/std-lib/Standard/src/Base/Network/Http/Status_Code.enso +++ b/distribution/std-lib/Standard/src/Base/Network/Http/Status_Code.enso @@ -2,7 +2,10 @@ from Standard.Base import all type Status_Code - ## HTTP status code. + ## An HTTP status code. + + Arguments: + - code: The numeric representation of the code. type Status_Code code ## 100 Continue. diff --git a/distribution/std-lib/Standard/src/Base/Network/Internal.enso b/distribution/std-lib/Standard/src/Base/Network/Internal.enso index 9a6c761062..d371766ebe 100644 --- a/distribution/std-lib/Standard/src/Base/Network/Internal.enso +++ b/distribution/std-lib/Standard/src/Base/Network/Internal.enso @@ -1,8 +1,17 @@ from Standard.Base import all ## PRIVATE + + Panics on encountering an error. + + Arguments: + - action: The action to perform that may recurn an error. +panic_on_error : Any -> Any panic_on_error ~action = action . catch Panic.throw ## PRIVATE + + Recovers from a panic. +recover_panic : Any -> Error recover_panic error = Error.throw error diff --git a/distribution/std-lib/Standard/src/Base/Network/Proxy.enso b/distribution/std-lib/Standard/src/Base/Network/Proxy.enso index 49e7562a76..36be2a4425 100644 --- a/distribution/std-lib/Standard/src/Base/Network/Proxy.enso +++ b/distribution/std-lib/Standard/src/Base/Network/Proxy.enso @@ -3,15 +3,23 @@ from Standard.Base import all ## Proxy settings. type Proxy - ## Proxy is disabled. + ## The proxy is disabled. type None - ## Use a sysem proxy settings. + ## Use the system proxy settings. type System - ## Use provided proxy. + ## Use the provided proxy server. type Proxy_Addr proxy_host proxy_port -## Create new proxy settins from host and port. +## Create new proxy settings from a host and port. + + Arguments: + - host: The host address for the proxy. + - port: The port number for the proxy server on `host`. + + > Example + Create a new proxy running on localhost at port 80080. + Proxy.new "localhost" 80800 new : Text -> Integer -> Proxy new host port=80 = Proxy_Addr host port diff --git a/distribution/std-lib/Standard/src/Base/Network/Uri.enso b/distribution/std-lib/Standard/src/Base/Network/Uri.enso index 193f49b393..952c49eadf 100644 --- a/distribution/std-lib/Standard/src/Base/Network/Uri.enso +++ b/distribution/std-lib/Standard/src/Base/Network/Uri.enso @@ -6,23 +6,58 @@ polyglot java import java.net.URI as Java_URI polyglot java import java.util.Optional ## Syntax error when parsing a Uri. + + Arguments: + - message: The error message for the URI syntax error. type Syntax_Error message +## Converts the URI syntax error to a human-readable form. Syntax_Error.to_display_text = "Uri syntax error: " + this.message -## Convert Text to Uri. +## Parse a Uri from text. + + Arguments: + - text: The text to parse as a URI. + + Throws a Syntax_Error when the text cannot be parsed as a Uri. + + > Example + Parse Uri text. + Uri.parse "http://example.com" +parse : Text -> Uri ! Syntax_Error +parse text = + Panic.recover (Uri (Java_URI.create text)) . catch e-> case e of + Polyglot_Error ex -> Error.throw (Syntax_Error ex.getMessage) + other -> Panic.throw other + +## Convert Text to a Uri. + + Throws a Syntax_Error when `this` cannot be parsed as a Uri. + + > Example + Parse Uri text. + Uri.parse "http://example.com" +Text.to_uri : Uri ! Syntax_Error Text.to_uri = here.parse this type Uri + ## Represents a Uniform Resource Identifier (URI) reference. + + Arguments: + - internal_uri: The internal representation of the URI. type Uri internal_uri ## Convert this to Uri. + + > Examples + Convert a URI to a URI (a no op). + "http://example.com".to_uri.to_uri to_uri : Uri to_uri = this - ## Get scheme part of this Uri. + ## Get the scheme part of this Uri. > Example Return the "http" part of the HTTP address. @@ -31,7 +66,7 @@ type Uri scheme : Text ! Nothing scheme = Internal.handle_nothing this.internal_uri.getScheme - ## Get user info part of this Uri. + ## Get the user info part of this Uri. > Example Return the "user:pass" part of the HTTP address. @@ -40,7 +75,7 @@ type Uri user_info : Text ! Nothing user_info = Internal.handle_nothing this.internal_uri.getUserInfo - ## Get host part of this Uri. + ## Get the host part of this Uri. > Example Return the "example.com" part of the HTTP address. @@ -49,7 +84,7 @@ type Uri host : Text ! Nothing host = Internal.handle_nothing this.internal_uri.getHost - ## Get authority (user info and host) part of this Uri. + ## Get the authority (user info and host) part of this Uri. > Example Return the "user:pass@example.com" part of the HTTP address. @@ -58,7 +93,7 @@ type Uri authority : Text ! Nothing authority = Internal.handle_nothing this.internal_uri.getAuthority - ## Get port part of this Uri. + ## Get the port part of this Uri. > Example Return the "80" part of the HTTP address. @@ -75,7 +110,7 @@ type Uri Internal.handle_nothing <| if port_number == -1 then Nothing else port_number.to_text - ## Get path part of this Uri. + ## Get the path part of this Uri. > Example Return the "/foo/bar" part of the HTTP address. @@ -84,7 +119,7 @@ type Uri path : Text ! Nothing path = Internal.handle_nothing this.internal_uri.getPath - ## Get query part of this Uri. + ## Get the query part of this Uri. > Example Return the "key=val" part of the HTTP address. @@ -93,7 +128,7 @@ type Uri query : Text ! Nothing query = Internal.handle_nothing this.internal_uri.getQuery - ## Get fragment part of this Uri. + ## Get the fragment part of this Uri. > Example Return the empty fragment of the HTTP address. @@ -102,46 +137,57 @@ type Uri fragment : Text ! Nothing fragment = Internal.handle_nothing this.internal_uri.getFragment - ## Get unescaped user info part of this Uri. + ## ADVANCED + + Get the unescaped user info part of this Uri. raw_user_info : Text ! Nothing raw_user_info = Internal.handle_nothing this.internal_uri.getRawUserInfo - ## Get unescaped authority part of this Uri. + ## ADVANCED + + Get the unescaped authority part of this Uri. raw_authority : Text ! Nothing raw_authority = Internal.handle_nothing this.internal_uri.getRawAuthority - ## Get unescaped path part of this Uri. + ## ADVANCED + + Get the unescaped path part of this Uri. raw_path : Text ! Nothing raw_path = Internal.handle_nothing this.internal_uri.getRawPath - ## Get unescaped query part of this Uri. + ## ADVANCED + + Get the unescaped query part of this Uri. raw_query : Text ! Nothing raw_query = Internal.handle_nothing this.internal_uri.getRawQuery - ## Get unescaped fragment part of this Uri. + ## ADVANCED + + Get the unescaped fragment part of this Uri. raw_fragment : Text ! Nothing raw_fragment = Internal.handle_nothing this.internal_uri.getRawFragment ## Convert this Uri to text. + + > Example + Convert a URI to text. + Uri.new "https://example.com" . to_text to_text : Text to_text = this.internal_uri.toString - ## An Uri to JSON conversion. + ## Convert a Uri to JSON. + + > Example + Convert a URI to JSON. + Uri.new "https://example.com" . to_json to_json : Json.String to_json : Json.String this.to_text - ## Check Uri equality. + ## Check if this URI is equal to another URI. + + > Example + Check if two URIs are equal. + "https://example.com" == "http://example.com" == : Uri -> Boolean == that = this.internal_uri.equals that.internal_uri -## Parse Uri from text. - Return Syntax_Error when the text cannot be parsed as Uri. - - > Example - Parse Uri text. - Uri.parse "http://example.com" -parse : Text -> Uri ! Syntax_Error -parse text = - Panic.recover (Uri (Java_URI.create text)) . catch e-> case e of - Polyglot_Error ex -> Error.throw (Syntax_Error ex.getMessage) - other -> Panic.throw other diff --git a/distribution/std-lib/Standard/src/Base/Network/Uri/Internal.enso b/distribution/std-lib/Standard/src/Base/Network/Uri/Internal.enso index 392d682589..200521e26d 100644 --- a/distribution/std-lib/Standard/src/Base/Network/Uri/Internal.enso +++ b/distribution/std-lib/Standard/src/Base/Network/Uri/Internal.enso @@ -1,6 +1,11 @@ from Standard.Base import all ## PRIVATE + + Handle a nothing value. + + Arguments: + - value: The value that may possibly be nothing. handle_nothing : Any -> Any ! Nothing handle_nothing value = case value of Nothing -> Error.throw Nothing diff --git a/distribution/std-lib/Standard/src/Base/Polyglot/Java.enso b/distribution/std-lib/Standard/src/Base/Polyglot/Java.enso index 5575972f9f..212cddddd1 100644 --- a/distribution/std-lib/Standard/src/Base/Polyglot/Java.enso +++ b/distribution/std-lib/Standard/src/Base/Polyglot/Java.enso @@ -2,7 +2,13 @@ from Standard.Base import all import Builtins -## Checks whether an object is an instance of a given class. +## PRIVATE + + Checks whether an object is an instance of a given class. + + Arguments: + - object: The object to check for class membership. + - class: The java class to check for membership in. Builtins.Java.is_instance : Any -> Any -> Boolean Builtins.Java.is_instance object class = class_object = class.class diff --git a/distribution/std-lib/Standard/src/Base/System/Environment.enso b/distribution/std-lib/Standard/src/Base/System/Environment.enso index a82e93c958..d5aab1c502 100644 --- a/distribution/std-lib/Standard/src/Base/System/Environment.enso +++ b/distribution/std-lib/Standard/src/Base/System/Environment.enso @@ -6,6 +6,13 @@ polyglot java import java.lang.System Returns a value of a specified environment variable or Nothing if such variable is not defined. + + Arguments: + - key: The name of the environment variable to look up. + + > Example + Look up the value of the `PATH` environment variable. + Environment.get "PATH" get : Text -> Text | Nothing get key = System.getenv key diff --git a/distribution/std-lib/Standard/src/Base/System/File.enso b/distribution/std-lib/Standard/src/Base/System/File.enso index bb802dd945..c7e3444f2e 100644 --- a/distribution/std-lib/Standard/src/Base/System/File.enso +++ b/distribution/std-lib/Standard/src/Base/System/File.enso @@ -10,121 +10,102 @@ polyglot java import java.nio.file.AccessDeniedException polyglot java import java.nio.file.NoSuchFileException type File_Error + + ## An error that indicates that the requested file does not exist. + + Arguments: + - file: The file that doesn't exist. type No_Such_File_Error file + + ## An error that indicates that the program does not have access to the + requested file. + + Arguments: + - file: The file that the program does not have permission to access. type Access_Denied_Error file + + ## A generic IO error. + + Arguments: + - message: The message for the error. type Io_Error message -## PRIVATE + ## UNSTABLE - Utility method for rewrapping Java exceptions into Enso panics. -rethrow_java file exception = - case exception of - Polyglot_Error exc -> - if Java.is_instance exc NoSuchFileException then - Panic.throw (No_Such_File_Error file) - if Java.is_instance exc AccessDeniedException then - Panic.throw (Access_Denied_Error file) - if Java.is_instance exc IOException then - Panic.throw (Io_Error exc.getMessage) - Panic.throw exception - _ -> Panic.throw exception + Convert the File error to a human-readable format. + to_display_text : Text + to_display_text = case this of + No_Such_File_Error file -> "The file at " + file.path + " does not exist." + Access_Denied_Error file -> "You do not have permission to access the file at " + file.path + "." + Io_Error msg -> "An IO error has occurred: " + msg.to_text + "." -## PRIVATE +## Creates a new file object, pointing to the given path. - Utility method for running an action with Java exceptions mapping. -handle_java_exceptions file ~action = - err = Panic.recover action - r = err.catch (here.rethrow_java file) - r + Arguments: + - path: The path to the file that you want to create. -## PRIVATE + > Example + Create a new file pointing to the `data.csv` file in the project directory. + File.new (Enso_Project.data / "data.csv").path +new : Text -> File +new path = File (Prim_Io.get_file path) - Utility method for closing primitive Java streams. Provided to avoid - accidental scope capture with `Managed_Resource` finalizers. -close_stream : Any -> Nothing -close_stream stream = - stream.close - Nothing +## Open and read the file at the provided `path`. -## An output stream, allowing for interactive writing of contents into an - open file. -type Output_Stream - type Output_Stream file stream_resource + Arguments: + - path: The path of the file to open and read the contents of. It will + accept a textual path or a file. - ## Writes a vector of bytes into the file at the current stream position. - write_bytes : Vector.Vector -> Nothing ! File_Error - write_bytes contents = Managed_Resource.with this.stream_resource java_stream-> - here.handle_java_exceptions this.file <| - java_stream.write contents.to_array - java_stream.flush - Nothing + ? Module or Instance? + If you have a variable `file` of type `File`, we recommend calling the + `.read` method on it directly, rather than using `File.read file`. The + latter, however, will still work. - ## Closes this stream. + > Example + Read the `data.csv` file in the project directory's `data` directory. You + will need to create the file `data.csv` manually in that directory. + File.read (Enso_Project.data / "data.csv").path +read : (Text | File) -> Text +read path = .read <| case path of + Text -> (here.new path) + File _ -> path - Even though Streams are closed automatically upon garbage collection, it - is still advised to close streams manually if they are not used within - a bracket pattern. - close : Nothing - close = Managed_Resource.finalize this.stream_resource +## Returns the current working directory (CWD) of the current program. -## An input stream, allowing for interactive reading of contents from an open - file. -type Input_Stream - type Input_Stream file stream_resource + > Example + Get the program's current working directory. + File.current_directory +current_directory : File +current_directory = File (Prim_Io.get_cwd) - ## Reads all the bytes in this file into a vector of bytes. - read_all_bytes : Vector.Vector ! File_Error - read_all_bytes = Managed_Resource.with this.stream_resource java_stream-> - here.handle_java_exceptions this.file <| - Vector.from_polyglot_array java_stream.readAllBytes +## Returns the home directory of the current user. - ## Reads _up to_ the provided number of bytes from the stream. - - Makes a best-effort to read as many bytes as provided, however fewer - bytes may be read, if end of stream is encountered. - - The length of the returned vector is the same as the number of bytes - read. - read_n_bytes : Integer -> Vector.Vector ! File_Error - read_n_bytes n = Managed_Resource.with this.stream_resource java_stream-> - here.handle_java_exceptions this.file <| - bytes = java_stream.readNBytes n - Vector.from_polyglot_array bytes - - ## Reads the next byte from the stream. - - The returned value is an integer in the range 0-255 representing the - next byte of input, or -1 if end of stream is reached. - read_byte : Integer ! File_Error - read_byte = Managed_Resource.with this.stream_resource java_stream-> - here.handle_java_exceptions this.file <| - java_stream.read - - ## Closes this stream. - - Even though Streams are closed automatically upon garbage collection, it - is still advised to close streams manually if they are not used within - a bracket pattern. - close : Nothing - close = Managed_Resource.finalize this.stream_resource - - ## Exposes operations on the underlying Java input stream. - - Useful when integrating with polyglot functions requiring an - `InputStream` as an argument. - with_java_stream : (Java_Input_Stream -> Any) -> Any - with_java_stream f = Managed_Resource.with this.stream_resource f + > Example + Get the current user's home directory. + File.home +home : File +home = here.new (Prim_Io.get_user_home) type File + + ## PRIVATE + + A type representing a file. + + Arguments: + - prim_file: The internal representation of the file. type File prim_file - ## Returns a new input stream for this file. + ## ADVANCED + + Returns a new input stream for this file. + + Arguments: + - open_options: A vector of `File.Option` objects determining how to open + the stream. These options set the access properties of the stream. The returned stream should be closed as soon as it is not used anymore. The `with_input_stream` method should be preferred whenever possible. - - The `open_options` argument is a vector of `File.Option` objects, - describing the access properties of the created stream. new_input_stream : Vector.Vector -> Input_Stream ! File_Error new_input_stream open_options = opts = open_options . map (_.to_java) . to_array @@ -133,13 +114,16 @@ type File resource = Managed_Resource.register stream here.close_stream Input_Stream this resource - ## Returns a new output stream for this file. + ## ADVANCED + + Returns a new output stream for this file. + + Arguments: + - open_options: A vector of `File.Option` objects determining how to open + the stream. These options set the access properties of the stream. The returned stream should be closed as soon as it is not used anymore. The `with_output_stream` method should be preferred whenever possible. - - The `open_options` argument is a vector of `File.Option` objects, - describing the access properties of the created stream. new_output_stream : Vector.Vector -> Output_Stream ! File_Error new_output_stream open_options = opts = open_options . map (_.to_java) . to_array @@ -151,11 +135,14 @@ type File ## Creates a new output stream for this file and runs the specified action on it. + Arguments: + - open_options: A vector of `File.Option` objects determining how to open + the stream. These options set the access properties of the stream. + - action: A function that operates on the output stream and returns some + value. The value is returned from this method. + The created stream is automatically closed when `action` returns (even if it returns exceptionally). - - The `open_options` argument is a vector of `File.Option` objects, - describing the properties of the created stream. with_output_stream : Vector.Vector -> (Output_Stream -> Any ! File_Error) -> Any ! File_Error with_output_stream open_options action = Resource.bracket (this.new_output_stream open_options) (_.close) action @@ -163,11 +150,14 @@ type File ## Creates a new input stream for this file and runs the specified action on it. + Arguments: + - open_options: A vector of `File.Option` objects determining how to open + the stream. These options set the access properties of the stream. + - action: A function that operates on the input stream and returns some + value. The value is returned from this method. + The created stream is automatically closed when `action` returns (even if it returns exceptionally). - - The `open_options` argument is a vector of `File.Option` objects, - describing the properties of the created stream. with_input_stream : Vector.Vector -> (Input_Stream -> Any ! File_Error) -> Any ! File_Error with_input_stream open_options action = Resource.bracket (this.new_input_stream open_options) (_.close) action @@ -185,16 +175,25 @@ type File Text.from_utf_8 bytes ## Appends a number of bytes at the end of this file. + + Arguments: + - contents: A vector of bytes to append to the file. append_bytes : Vector.Vector -> Nothing ! File_Error append_bytes contents = opts = [Option.Append, Option.Create] this.with_output_stream opts (_.write_bytes contents) ## Appends a UTF-8 encoded `Text` at the end of this file. + + Arguments: + - contents: The UTF-8 encoded text to append to the file. append : Text -> Nothing ! File_Error append contents = this.append_bytes contents.utf_8 - ## Writes a number of bytes into this file, removing any existing contents. + ## Writes a number of bytes into this file, replacing any existing contents. + + Arguments: + - contents: The vector of bytes to write into the file. If the file does not exist, it will be created. write_bytes : Vector.Vector -> Nothing ! File_Error @@ -203,14 +202,20 @@ type File this.with_output_stream opts (_.write_bytes contents) Nothing - ## Writes a UTF-8 encoded `Text` into this file, removing any existing + ## Writes a UTF-8 encoded `Text` into this file, replacing any existing contents. + Arguments: + - contents: The UTF-8 encoded text to write to the file. + If the file does not exist, it will be created. write : Text -> Nothing ! File_Error write contents = this.write_bytes contents.utf_8 - ## Resolve a child file of the given file. + ## Join two path segments together. + + Arguments: + - subpath: The path to join to the path of `this`. / : (Text | File) -> File / subpath = case subpath of File prim -> File (this.prim_file.resolve prim) @@ -239,6 +244,11 @@ type File create_directory = this.prim_file.createDirectories ## Checks whether the file exists and is a regular file. + + ? Regular Files + A regular file is one that does not have any special meaning to the + operating system. Examples of files that are not regular are symlinks, + pipes, devices, sockets and directories. is_regular_file : Boolean is_regular_file = this.prim_file.isRegularFile @@ -288,38 +298,150 @@ type File delete_if_exists : Nothing ! File_Error delete_if_exists = if this.exists then this.delete else Nothing -## Creates a new file object, pointing to the given path. +## An output stream, allowing for interactive writing of contents into an + open file. +type Output_Stream - > Example - Create a new file pointing to the `data.csv` file in the project directory. - File.new (Enso_Project.data / "data.csv").path -new : Text -> File -new path = File (Prim_Io.get_file path) + ## ADVANCED -## Open and read the file at the provided `path`. + An output stream, allowing for interactive writing of contents into an + open file. + + Arguments: + - file: The file which the output stream will write into. + - stream_resource: The internal resource that represents the underlying + stream. + type Output_Stream file stream_resource + + ## ADVANCED + Writes a vector of bytes into the file at the current stream position. + + Arguments: + - contents: A vector of bytes to write into the file. + write_bytes : Vector.Vector -> Nothing ! File_Error + write_bytes contents = Managed_Resource.with this.stream_resource java_stream-> + here.handle_java_exceptions this.file <| + java_stream.write contents.to_array + java_stream.flush + Nothing + + ## ADVANCED + + Closes this stream. + + Even though Streams are closed automatically upon garbage collection, it + is still advised to close streams manually if they are not used within + a bracket pattern. + close : Nothing + close = Managed_Resource.finalize this.stream_resource + +## An input stream, allowing for interactive reading of contents from an open + file. +type Input_Stream + + ## ADVANCED + + An input stream, allowing for interactive reading of contents from an open + file. + + Arguments: + - file: The file from which the stream will read. + - stream_resource: The internal resource that represents the underlying + stream. + type Input_Stream file stream_resource + + ## ADVANCED + + Reads all the bytes in this file into a vector of bytes. + read_all_bytes : Vector.Vector ! File_Error + read_all_bytes = Managed_Resource.with this.stream_resource java_stream-> + here.handle_java_exceptions this.file <| + Vector.from_polyglot_array java_stream.readAllBytes + + ## ADVANCED + + Reads _up to_ the provided number of bytes from the stream. + + Arguments: + - n: The number of bytes to read from the file. + + Makes a best-effort to read as many bytes as provided, however fewer + bytes may be read, if end of stream is encountered. + + The length of the returned vector is the same as the number of bytes + read. + read_n_bytes : Integer -> Vector.Vector ! File_Error + read_n_bytes n = Managed_Resource.with this.stream_resource java_stream-> + here.handle_java_exceptions this.file <| + bytes = java_stream.readNBytes n + Vector.from_polyglot_array bytes + + ## ADVANCED + + Reads the next byte from the stream. + + The returned value is an integer in the range 0-255 representing the + next byte of input, or -1 if end of stream is reached. + read_byte : Integer ! File_Error + read_byte = Managed_Resource.with this.stream_resource java_stream-> + here.handle_java_exceptions this.file <| + java_stream.read + + ## ADVANCED + + Closes this stream. + + Even though Streams are closed automatically upon garbage collection, it + is still advised to close streams manually if they are not used within + a bracket pattern. + close : Nothing + close = Managed_Resource.finalize this.stream_resource + + ## PRIVATE + + Exposes operations on the underlying Java input stream. + + Arguments: + - f: Applies a function over the internal java stream. + + Useful when integrating with polyglot functions requiring an + `InputStream` as an argument. + with_java_stream : (Java_Input_Stream -> Any) -> Any + with_java_stream f = Managed_Resource.with this.stream_resource f + +## PRIVATE + + Utility method for rewrapping Java exceptions into Enso panics. Arguments: - - `path`: The path of the file to open and read the contents of. It will - accept a textual path or a file. + - file: The file object. + - exception: The java exception that was encountered. +rethrow_java : File -> Any -> Any +rethrow_java file exception = + case exception of + Polyglot_Error exc -> + if Java.is_instance exc NoSuchFileException then + Panic.throw (No_Such_File_Error file) + if Java.is_instance exc AccessDeniedException then + Panic.throw (Access_Denied_Error file) + if Java.is_instance exc IOException then + Panic.throw (Io_Error exc.getMessage) + Panic.throw exception + _ -> Panic.throw exception - ? Module or Instance? - If you have a variable `file` of type `File`, we recommend calling the - `.read` method on it directly, rather than using `File.read file`. The - latter, however, will work. +## PRIVATE - > Example - Read the `data.csv` file in the project directory's `data` directory. You - will need to create the file `data.csv` manually in that directory. - File.read (Enso_Project.data / "data.csv").path -read : (Text | File) -> Text -read path = .read <| case path of - Text -> (here.new path) - File _ -> path + Utility method for running an action with Java exceptions mapping. +handle_java_exceptions file ~action = + err = Panic.recover action + r = err.catch (here.rethrow_java file) + r -## Returns the current working directory (CWD) of the current program. -current_directory : File -current_directory = File (Prim_Io.get_cwd) +## PRIVATE -## Returns the home directory of the current user. -home : File -home = here.new (Prim_Io.get_user_home) + Utility method for closing primitive Java streams. Provided to avoid + accidental scope capture with `Managed_Resource` finalizers. +close_stream : Any -> Nothing +close_stream stream = + stream.close + Nothing diff --git a/distribution/std-lib/Standard/src/Base/System/File/Option.enso b/distribution/std-lib/Standard/src/Base/System/File/Option.enso index 5ba2470eda..1703b2f128 100644 --- a/distribution/std-lib/Standard/src/Base/System/File/Option.enso +++ b/distribution/std-lib/Standard/src/Base/System/File/Option.enso @@ -8,34 +8,45 @@ polyglot java import java.nio.file.StandardOpenOption file access. For most use cases, the default values used in the methods of the `File` type should be preferred. type Option + ## If the file is opened for `Write` access then bytes will be written to the end of the file rather than the beginning. type Append + ## Create a new file if it does not exist. type Create + ## Create a new file, failing if the file already exists. type Create_New + ## Delete the underlying file on closing the stream. type Delete_On_Close + ## Requires that every update to the file's content be written synchronously to the underlying storage device. type Dsync + ## Open for read access. type Read + ## Sparse file. type Sparse + ## Requires that every update to the file's content or metadata be written synchronously to the underlying storage device. type Sync + ## If the file already exists and is opened for `Write` access, the original contents will be removed. type Truncate_Existing + ## Open file for write access. type Write ## PRIVATE Convert this object into a representation understandable by the JVM. + to_java : StandardOpenOption to_java = case this of Append -> StandardOpenOption.APPEND Create -> StandardOpenOption.CREATE diff --git a/distribution/std-lib/Standard/src/Base/System/Platform.enso b/distribution/std-lib/Standard/src/Base/System/Platform.enso index 315cc67b86..aeb03fad3f 100644 --- a/distribution/std-lib/Standard/src/Base/System/Platform.enso +++ b/distribution/std-lib/Standard/src/Base/System/Platform.enso @@ -2,19 +2,20 @@ from Standard.Base import all from Builtins import System +## A representation of the various operating systems on which Enso can run. type Os - type Linux - type MacOS - type Windows - type Unknown -## PRIVATE - Create an Os object from text. -from_text: Text -> Os -from_text os = - if os == "linux" then Linux else - if os == "macos" then MacOS else - if os == "windows" then Windows else Unknown + ## The Linux operating system. + type Linux + + ## The macOS operating system. + type MacOS + + ## The Windows operating system. + type Windows + + ## An unknown operating system. + type Unknown ## Return the type of operating system. @@ -23,3 +24,12 @@ from_text os = Platform.os os : Os os = here.from_text System.os + +## PRIVATE + + Create an Os object from text. +from_text: Text -> Os +from_text os = + if os == "linux" then Linux else + if os == "macos" then MacOS else + if os == "windows" then Windows else Unknown diff --git a/distribution/std-lib/Standard/src/Base/System/Process.enso b/distribution/std-lib/Standard/src/Base/System/Process.enso index 1b4aa16691..b098edff35 100644 --- a/distribution/std-lib/Standard/src/Base/System/Process.enso +++ b/distribution/std-lib/Standard/src/Base/System/Process.enso @@ -3,15 +3,46 @@ import Standard.Base.System.Process.Exit_Code from Standard.Base.Data.Vector import Vector from Builtins import Array, System, True, False +## UNSTABLE + + Call a command with a list of arguments. + + > Example + Call the `echo` command with arguments + Process.run "echo" ["-n", "Hello!"] + The result is printed to stdout: + Hello! +run : Text -> Vector.Vector Text -> Exit_Code +run command arguments=[] = + result = System.create_process command arguments.to_array input="" redirect_in=True redirect_out=True redirect_err=True + Exit_Code.from_number result.exit_code + ## UNSTABLE The builder object that is used to create operating system processes. type Builder + + ## UNSTABLE + + A builder object that is used to create operating system processes. + + Arguments: + - command: The command to execute on the system. + - arguments: The arguments to pass to `command`. These must be text. + - stdin: Any content to pass to the standard input for `command`. + + ? Creating a Builder + We recommend that you use this type with its builder interface. Start + by creating a `Builder "command"` and then call functions on it to + set arguments and standard output. It results in much clearer code. type Builder command arguments=[] stdin="" ## UNSTABLE Sets the arguments that should be passed to the created process. + + Arguments: + - arguments: The arguments to pass to the process. set_arguments : Vector.Vector Text -> Builder set_arguments arguments = Builder this.command arguments this.stdin @@ -19,6 +50,9 @@ type Builder Sets the text that will be used to feed standard input to the created process. + + Arguments: + - stdin: The standard input contents to pass to the process. set_stdin : Text -> Builder set_stdin stdin = Builder this.command this.arguments stdin @@ -40,18 +74,10 @@ type Builder ## UNSTABLE The result of the process invocation. + + Arguments: + - exit_code: The exit code for the process. + - stdout: The contents of the process' standard output. + - stderr: The contents of the process' standard error. type Result exit_code stdout stderr -## UNSTABLE - - Call a command with a list of arguments. - - > Example - Call the `echo` command with arguments - Process.run "echo" ["-n", "Hello!"] - The result is printed to stdout: - Hello! -run : Text -> Vector.Vector Text -> Exit_Code -run command arguments=[] = - result = System.create_process command arguments.to_array input="" redirect_in=True redirect_out=True redirect_err=True - Exit_Code.from_number result.exit_code diff --git a/distribution/std-lib/Standard/src/Base/System/Process/Exit_Code.enso b/distribution/std-lib/Standard/src/Base/System/Process/Exit_Code.enso index f9f1c830ba..d5fdf79c5c 100644 --- a/distribution/std-lib/Standard/src/Base/System/Process/Exit_Code.enso +++ b/distribution/std-lib/Standard/src/Base/System/Process/Exit_Code.enso @@ -1,19 +1,34 @@ +from Standard.Base import all + ## The exit codes that the process can return. type Exit_Code + + ## The process exited with a success. type Exit_Success + + ## The process exited with a failure. + + Arguments: + - code: The exit code for the failure. type Exit_Failure code ## Convert exit code to a number. + + > Example + Convert a success code to a corresponding number. + Exit_Success.to_number + to_number : Integer to_number = case this of Exit_Success -> 0 Exit_Failure code -> code ## Create exit code from a number. + Arguments: + - code: The exit code you want to create. + > Example - Create failure exit code: + Create a failure exit code. Exit_Code.from_number 1 - Result in: - Exit_Failure 1 from_number : Number -> Exit_Code from_number code = if code == 0 then Exit_Success else Exit_Failure code diff --git a/distribution/std-lib/Standard/src/Database/Connection/Connection.enso b/distribution/std-lib/Standard/src/Database/Connection/Connection.enso index fae4fa852e..8d21f5d4b3 100644 --- a/distribution/std-lib/Standard/src/Database/Connection/Connection.enso +++ b/distribution/std-lib/Standard/src/Database/Connection/Connection.enso @@ -25,11 +25,11 @@ type Connection A Database connection using a JDBC driver. - Allows to access tables from a database. - Arguments: - java_connection: the resource managing the underlying JDBC connection. - dialect: the dialect associated with the database we are connected to. + + Allows accessing tables from a database. type Connection connection_resource dialect ## UNSTABLE @@ -106,6 +106,11 @@ type Connection _ -> Error.throw err ## PRIVATE + + Prepares the statement by ensuring that it is sanitised. + + Arguments: + - query: The query to prepare the SQL statement in. prepare_statement : Text | Sql.Statement -> PreparedStatement prepare_statement query = go template holes=[] = Managed_Resource.with this.connection_resource java_connection-> @@ -130,6 +135,9 @@ type Connection A helper function that fetches column names and sql types associated with them for a table in the database. + + Arguments: + - table_name: The name of the table to fetch the column metadata for. # fetch_columns : Text -> Vector [Text, Sql_Type] fetch_columns table_name = query = IR.Select_All (IR.make_ctx_from table_name) @@ -149,6 +157,9 @@ type Connection Creates a builder for a column based on a provided SQL type, trying to infer the best type for the builder. + + Arguments: + - sql_type: The SQL type of the column to create a builder for. create_builder : Sql_Type -> Builder create_builder sql_type = initial_size = 10 @@ -158,16 +169,37 @@ create_builder sql_type = Builder_Inferred (Java_Exports.make_inferred_builder initial_size) type Builder + ## PRIVATE + + A builder that has an inferred column type at runtime. + + Arguments: + - java_builder: The underlying builder object. type Builder_Inferred java_builder ## PRIVATE + + A builder that has an inferred column type at runtime. + + Arguments: + - java_builder: The underlying builder object. type Builder_Double java_builder ## PRIVATE + + A builder that has an inferred column type at runtime. + + Arguments: + - java_builder: The underlying builder object. type Builder_Long java_builder ## PRIVATE + + A builder that has an inferred column type at runtime. + + Arguments: + - java_builder: The underlying builder object. type Builder_Boolean java_builder ## PRIVATE @@ -202,6 +234,9 @@ type Builder ## PRIVATE Seals the builder and returns a built Java-column. + + Argument: + - name: The name of the column. make_column : Text -> Java_Exports.Column make_column name = storage = this.java_builder.seal @@ -209,12 +244,24 @@ type Builder ## An error indicating that a supported dialect could not be deduced for the provided URL. + + Argument: + - url: The URL for which the dialect could not be deduced. type Unsupported_Dialect url +## Pretty print the error about unsupported SQL dialects. +Unsupported_Dialect.to_display_text : Text +Unsupported_Dialect.to_display_text = + "Could not infer the SQL dialect for the database at " + this.url + "." + ## PRIVATE Creates a JDBC connection based on a URL and optionally username and password. + + Arguments: + - url: The URL to connect to. + - properties: A vector of properties for the connection. create_jdbc_connection : Text -> Vector -> Connection create_jdbc_connection url properties = here.wrap_sql_errors <| java_props = Properties.new @@ -228,37 +275,55 @@ create_jdbc_connection url properties = here.wrap_sql_errors <| ## PRIVATE This cannot be a closure due to limitations of Managed_Resource. + + Arguments: + - connection: The connection to close. +close_connection : Connection -> Nothing close_connection connection = connection.close type Sql_Error + ## UNSTABLE Indicates an error with executing a query, update or connecting to the database. - Wraps an SQLException from the Java drvier. + Arguments: + - java_exception: The underlying exception. type Sql_Error java_exception ## UNSTABLE + + Convert the SQL error to a textual representation. to_text : Text - to_text = this.java_exception.getMessage + to_text = "There was an SQL error: " + this.java_exception.getMessage.to_text + "." ## UNSTABLE + + Pretty print the SQL error. to_display_text : Text to_display_text = this.to_text type Sql_Timeout_Error + ## UNSTABLE Indicates that an operation has timed out. + + Arguments: + - java_exception: The underlying exception. type Sql_Timeout_Error java_exception ## UNSTABLE + + Convert the timeout error to a textual representation. to_text : Text - to_text = this.java_exception.getMessage + to_text = "The SQL connection timed out: " + this.java_exception.getMessage + "." ## UNSTABLE + + Pretty print the timeout error. to_display_text : Text to_display_text = this.to_text @@ -266,6 +331,9 @@ type Sql_Timeout_Error Executes `action` and returns its result, catching any panics and if they are coming from JDBC, wraps them with our own error types. + + Arguments: + - action: The computation to execute. This computation may throw SQL errors. wrap_sql_errors ~action = result = Panic.recover action result.catch err-> case err of diff --git a/distribution/std-lib/Standard/src/Database/Connection/Database.enso b/distribution/std-lib/Standard/src/Database/Connection/Database.enso index bee42ce0b9..ac4d293a76 100644 --- a/distribution/std-lib/Standard/src/Database/Connection/Database.enso +++ b/distribution/std-lib/Standard/src/Database/Connection/Database.enso @@ -6,31 +6,32 @@ from Standard.Database.Connection.Connection import all Tries to connect to the database under a provided URL. - Currently SQLite and PostgreSQL databases are supported. - - The exact URL depends on the database engine. - For SQLite the expected format is `sqlite:/path/to/database/file`. - For PostgreSQL it can be one of: - - `postgresql:database_name` - which will connect to the database with the - given name on the local machine; - - `postgresql:/` - which will connect to the default database - (which is the same as the username) on the local machine; - - `postgresql://host/database_name` - which will connect to the specified - database on a specified host, the `host` can consist of an IP address or a - hostname, optionally followed by colon and a port number, so values like - `db.example.com`, `127.0.0.1`, `example.com:1234`, `127.0.0.1:1234` are - allowed; - - `postgresql://host/` - which will connect to the same database as the - username on a specified host, the `host`` is defined as above. - Arguments: - - url: the URL to connect to. - - user: (optional) an username for authentication. - - password: (optional) a password for authentication. - - custom_properties: (optional) a vector of key-value Text pairs which can + - url: The URL to connect to. + - user: A username for authentication. Optional. + - password: A password for authentication. Optional. + - custom_properties: A vector of key-value Text pairs which can set any other properties that can be used to configure the connection or for authentication. Supported properties depend on the database engine that - the connection is made to. + the connection is made to. Optional. + + Currently SQLite and PostgreSQL databases are supported. + + ? Finding the URL + The exact URL depends on the database engine. For SQLite the expected o + format is `sqlite:/path/to/database/file`. For PostgreSQL it can be one + of: + - `postgresql:database_name` - which will connect to the database with the + given name on the local machine; + - `postgresql:/` - which will connect to the default database + (which is the same as the username) on the local machine; + - `postgresql://host/database_name` - which will connect to the specified + database on a specified host, the `host` can consist of an IP address or= + a hostname, optionally followed by colon and a port number, so values + like `db.example.com`, `127.0.0.1`, `example.com:1234`, `127.0.0.1:1234` + are allowed; + - `postgresql://host/` - which will connect to the same database as the + username on a specified host, the `host`` is defined as above. connect : Text -> Nothing | Text -> Nothing | Text -> Vector -> Connection ! Sql_Error connect url user=Nothing password=Nothing custom_properties=[] = full_url = if url.starts_with "jdbc:" then url else "jdbc:"+url @@ -43,10 +44,10 @@ connect url user=Nothing password=Nothing custom_properties=[] = Connects to an SQLite database in a file on the filesystem. - It is an alternative to `connect` that resolves a path to the database file. - Arguments: - - file: the path to the database. + - file: The path to the database. + + It is an alternative to `connect` that resolves a path to the database file. open_sqlite_file : File -> Connection ! Sql_Error open_sqlite_file file = url = "sqlite:" + file.absolute.path diff --git a/distribution/std-lib/Standard/src/Database/Data/Column.enso b/distribution/std-lib/Standard/src/Database/Data/Column.enso index 43505257ac..ccc7f2560b 100644 --- a/distribution/std-lib/Standard/src/Database/Data/Column.enso +++ b/distribution/std-lib/Standard/src/Database/Data/Column.enso @@ -15,6 +15,12 @@ type Column Represents a single column backed by a database. + Arguments: + - name: The name of the column. + - connection: The connection with which the column is associated. + - expression: The expressions to apply to the column. + - context: The SQl context in which the column exists. + These columns may come from the Table or can be created by combining other columns with operators. Expressions created in this way may be materialized or used to apply filters, groupings etc. to tables from @@ -43,6 +49,7 @@ type Column Arguments: - show_rows: the number of initial rows that should be displayed. + print : Nothing print show_rows=10 = IO.println (this.display show_rows format_terminal=True) IO.println '' @@ -93,6 +100,14 @@ type Column ## PRIVATE Creates a binary operation with given kind and operand. + + Arguments: + - op_kind: The kind of binary operator. + - operand: The right operand to the binary operator. + - new_type: The type of the SQL column that results from applying the + operator. + - operand_type: The SQL type of the operand. + If not specified, the `new_type` is the same as the current one. `operand_type` is only relevant if the operand is not a column, it defaults to the current type if not provided. @@ -116,6 +131,11 @@ type Column ## PRIVATE Helper for implementing unary operators. + + Arguments: + - op_kind: The kind of the unary operator. + - new_type: The type of the SQL column that results from applying the + operator. make_unary_op : Text -> Text -> (Sql_Type | Nothing) -> Column make_unary_op op_kind new_type=Nothing = actual_new_type = if new_type.is_nothing then this.sql_type else new_type @@ -147,6 +167,12 @@ type Column mean = this.compute_aggregate "AVG" ## PRIVATE + + Computes an aggregate operator. + + Arguments: + - op_name: The name of the operator to compute. + compute_aggregate : Text compute_aggregate op_name = agg = here.make_aggregate this op_name agg.to_vector . at 0 @@ -171,109 +197,159 @@ type Column ## UNSTABLE - Element-wise equality comparison. Returns a column with results of - comparing this column's elements against `other`. - If `other` is a column, the comparison is performed pairwise between - corresponding elements of `this` and `other`. + Element-wise equality comparison. + + Arguments: + - other: The other column to compare pairwise with. + + Returns a column with results of comparing this column's elements against + `other`. If `other` is a column, the comparison is performed pairwise + between corresponding elements of `this` and `other`. == : Column | Any -> Column == other = this.make_binary_op "=" other new_type=Sql_Type.boolean ## UNSTABLE - Element-wise non-equality comparison. Returns a column with results of - comparing this column's elements against `other`. - If `other` is a column, the comparison is performed pairwise between - corresponding elements of `this` and `other`. + Element-wise non-equality comparison. + + Arguments: + - other: The other column to compare pairwise with. + + Returns a column with results of comparing this column's elements against + `other`. If `other` is a column, the comparison is performed pairwise + between corresponding elements of `this` and `other`. != : Column | Any -> Column != other = this.make_binary_op "!=" other new_type=Sql_Type.boolean ## UNSTABLE - Element-wise order comparison. Returns a column with results of - comparing this column's elements against `other`. - If `other` is a column, the comparison is performed pairwise between - corresponding elements of `this` and `other`. + Element-wise order comparison. + + Arguments: + - other: The other column to compare pairwise with. + + Returns a column with results of comparing this column's elements against + `other`. If `other` is a column, the comparison is performed pairwise + between corresponding elements of `this` and `other`. >= : Column | Any -> Column >= other = this.make_binary_op ">=" other new_type=Sql_Type.boolean ## UNSTABLE - Element-wise order comparison. Returns a column with results of - comparing this column's elements against `other`. - If `other` is a column, the comparison is performed pairwise between - corresponding elements of `this` and `other`. + Element-wise order comparison. + + Arguments: + - other: The other column to compare pairwise with. + + Returns a column with results of comparing this column's elements against + `other`. If `other` is a column, the comparison is performed pairwise + between corresponding elements of `this` and `other`. <= : Column | Any -> Column <= other = this.make_binary_op "<=" other new_type=Sql_Type.boolean ## UNSTABLE - Element-wise order comparison. Returns a column with results of - comparing this column's elements against `other`. - If `other` is a column, the comparison is performed pairwise between - corresponding elements of `this` and `other`. + Element-wise order comparison. + + Arguments: + - other: The other column to compare pairwise with. + + Returns a column with results of comparing this column's elements against + `other`. If `other` is a column, the comparison is performed pairwise + between corresponding elements of `this` and `other`. > : Column | Any -> Column > other = this.make_binary_op ">" other new_type=Sql_Type.boolean ## UNSTABLE - Element-wise order comparison. Returns a column with results of - comparing this column's elements against `other`. - If `other` is a column, the comparison is performed pairwise between - corresponding elements of `this` and `other`. + Element-wise order comparison. + + Arguments: + - other: The other column to compare pairwise with. + + Returns a column with results of comparing this column's elements against + `other`. If `other` is a column, the comparison is performed pairwise + between corresponding elements of `this` and `other`. < : Column | Any -> Column < other = this.make_binary_op "<" other new_type=Sql_Type.boolean ## UNSTABLE - Element-wise addition. Returns a column containing the result - of adding `other` to each element of `this`. - If `other` is a column, the operation is performed pairwise between - corresponding elements of `this` and `other`. + Element-wise addition. + + Arguments: + - other: The other column to add to this column. + + Returns a column containing the result of adding `other` to each element + of `this`. If `other` is a column, the operation is performed pairwise + between corresponding elements of `this` and `other`. + : Column | Any -> Column + other = this.make_binary_op "+" other ## UNSTABLE - Element-wise subtraction. Returns a column containing the result - of subtracting `other` from each element of `this`. - If `other` is a column, the operation is performed pairwise between - corresponding elements of `this` and `other`. + Element-wise subtraction. + + Arguments: + - other: The other column to subtract from this column. + + Returns a column containing the result of subtracting `other` from each + element of `this`. If `other` is a column, the operation is performed + pairwise between corresponding elements of `this` and `other`. - : Column | Any -> Column - other = this.make_binary_op "-" other ## UNSTABLE - Element-wise multiplication. Returns a column containing the result - of multiplying `other` by each element of `this`. - If `other` is a column, the operation is performed pairwise between - corresponding elements of `this` and `other`. + Element-wise multiplication. + + Arguments: + - other: The other column to multiply `this` by. + + Returns a column containing the result of multiplying `other` by each + element of `this`. If `other` is a column, the operation is performed + pairwise between corresponding elements of `this` and `other`. * : Column | Any -> Column * other = this.make_binary_op "*" other ## UNSTABLE - Element-wise division. Returns a column containing the result - of dividing each element of `this` by `other`. - If `other` is a column, the operation is performed pairwise between - corresponding elements of `this` and `other`. + Element-wise division. + + Arguments: + - other: The other column to divide `this` column by. + + Returns a column containing the result of dividing each element of `this` + by `other`. If `other` is a column, the operation is performed pairwise + between corresponding elements of `this` and `other`. / : Column | Any -> Column / other = this.make_binary_op "/" other ## UNSTABLE - Element-wise boolean conjunction. Returns a column containing the result - of performing the boolean `and` on `other` and each element of `this`. - If `other` is a column, the operation is performed pairwise between - corresponding elements of `this` and `other`. + Element-wise boolean conjunction. + + Arguments: + - other: The other column to compute the conjunction with. + + Returns a column containing the result of performing the boolean `and` on + `other` and each element of `this`. If `other` is a column, the + operation is performed pairwise between corresponding elements of `this` ] + and `other`. && : Column | Any -> Column && other = this.make_binary_op "AND" other ## UNSTABLE - Element-wise boolean disjunction. Returns a column containing the result - of performing the boolean `or` on `other` and each element of `this`. - If `other` is a column, the operation is performed pairwise between - corresponding elements of `this` and `other`. + Element-wise boolean disjunction. + + Arguments: + - other: The other column to compute the disjunction with. + + Returns a column containing the result of performing the boolean `or` on + `other` and each element of `this`. If `other` is a column, the + operation is performed pairwise between corresponding elements of `this` + and `other`. || : Column | Any -> Column || other = this.make_binary_op "OR" other @@ -300,8 +376,13 @@ type Column ## UNSTABLE Selects only the rows of this column that correspond to `True` values in - `indexes`. + `filter`. + + Arguments: + - filter: A column of booleans to mask `this` by. + This is useful for filtering the rows by given predicate. + > Example Select only the rows of `my_column` where the `status_column` column has the value `"Valid"` @@ -325,6 +406,9 @@ type Column ## UNSTABLE Returns the same column with changed name. + + Arguments: + - new_name: The name to rename `this` column to. rename : Text -> Column rename new_name = case Helpers.ensure_name_is_sane new_name of True -> @@ -339,8 +423,8 @@ type Column Sorts the column according to the specified rules. Arguments: - - order: specifies the default sort order for this operation. - - missing_last: specifies the default placement of missing values when + - order: Specifies the default sort order for this operation. + - missing_last: Specifies the default placement of missing values when compared to non-missing ones. Note thet this argument is independent from `order`, i.e. missing values will always be sorted according to this rule, ignoring the ascending / descending setting. @@ -360,33 +444,42 @@ type Column ## UNSTABLE Checks for each element of the column if it starts with `other`. - If `other` is a column, the operation is performed pairwise between - corresponding elements of `this` and `other`. - If the argument is a missing value (a Nothing or a column with missing - values), the behaviour on these missing values is vendor specific. + Arguments: + - other: A column or text to check for each item in `this`. + + If `other` is a column, the operation is performed pairwise between + corresponding elements of `this` and `other`. If the argument is a + missing value (a Nothing or a column with missing values), the behaviour + on these missing values is vendor specific. starts_with : Column | Text -> Column starts_with other = this.make_binary_op "starts_with" other new_type=Sql_Type.boolean ## UNSTABLE Checks for each element of the column if it ends with `other`. - If `other` is a column, the operation is performed pairwise between - corresponding elements of `this` and `other`. - If the argument is a missing value (a Nothing or a column with missing - values), the behaviour on these missing values is vendor specific. + Arguments: + - other: A column ot text to check for each item in `this`. + + If `other` is a column, the operation is performed pairwise between + corresponding elements of `this` and `other`. If the argument is a + missing value (a Nothing or a column with missing values), the behaviour + on these missing values is vendor specific. ends_with : Column | Text -> Column ends_with other = this.make_binary_op "ends_with" other new_type=Sql_Type.boolean ## UNSTABLE Checks for each element of the column if it contains `other`. - If `other` is a column, the operation is performed pairwise between - corresponding elements of `this` and `other`. - If the argument is a missing value (a Nothing or a column with missing - values), the behaviour on these missing values is vendor specific. + Arguments: + - other: A column ot text to check for each item in `this`. + + If `other` is a column, the operation is performed pairwise between + corresponding elements of `this` and `other`. If the argument is a + missing value (a Nothing or a column with missing values), the behaviour + on these missing values is vendor specific. contains : Column | Text -> Column contains other = this.make_binary_op "contains" other new_type=Sql_Type.boolean @@ -395,13 +488,22 @@ type Column as_internal = IR.Internal_Column this.name this.sql_type this.expression type Aggregate_Column + ## UNSTABLE - Wraps a column grouped by its index. Allows performing aggregation operations - on the contained values. - # type Aggregate_Column (name : Text) (connection : Connection) - # (sql_type : Sql_Type) (expression : IR.Expression) - # (context : IR.Context) + Wraps a column grouped by its index. + + Arguments: + - name: The name of the column. + - connection: The connection with which the column is associated. + - sql_type: The SQL type of the aggregate column. + - expression: The expressions to apply to the column. + - context: The SQl context in which the column exists. + + Allows performing aggregation operations on the contained values. + # type Aggregate_Column (name : Text) (connection : Connection) + # (sql_type : Sql_Type) (expression : IR.Expression) + # (context : IR.Context) type Aggregate_Column name connection sql_type expression context ## UNSTABLE @@ -409,8 +511,8 @@ type Aggregate_Column Sums the values in each group. Arguments: - - name_suffix: a suffix that will be appended to the original column - name to generate the resulting column name. + - name_suffix: a suffix that will be appended to the original column name + to generate the resulting column name. sum : Text -> Column sum name_suffix='_sum' = here.make_aggregate this "SUM" name_suffix @@ -420,8 +522,8 @@ type Aggregate_Column Computes the maximum element of each group. Arguments: - - name_suffix: a suffix that will be appended to the original column - name to generate the resulting column name. + - name_suffix: a suffix that will be appended to the original column name + to generate the resulting column name. max : Text -> Column max name_suffix='_max' = here.make_aggregate this "MAX" name_suffix @@ -431,8 +533,8 @@ type Aggregate_Column Computes the minimum element of each group. Arguments: - - name_suffix: a suffix that will be appended to the original column - name to generate the resulting column name. + - name_suffix: a suffix that will be appended to the original column name + to generate the resulting column name. min : Text -> Column min name_suffix='_min' = here.make_aggregate this "MIN" name_suffix @@ -442,8 +544,8 @@ type Aggregate_Column Computes the number of non-missing elements in each group. Arguments: - - name_suffix: a suffix that will be appended to the original column - name to generate the resulting column name. + - name_suffix: a suffix that will be appended to the original column name + to generate the resulting column name. count : Text -> Column count name_suffix='_count' = here.make_aggregate this "COUNT" name_suffix new_type=Sql_Type.integer @@ -453,15 +555,15 @@ type Aggregate_Column Computes the mean of non-missing elements in each group. Arguments: - - name_suffix: a suffix that will be appended to the original column - name to generate the resulting column name. + - name_suffix: a suffix that will be appended to the original column name + to generate the resulting column name. mean : Text -> Column mean name_suffix='_mean' = here.make_aggregate this "AVG" name_suffix ## PRIVATE - Helper that returns the underlying column from before grouping. + A helper that returns the underlying column from before grouping. ungrouped : Column ungrouped = new_ctx = this.context.set_groups [] @@ -471,6 +573,13 @@ type Aggregate_Column A helper method for creating an aggregated column by applying some operation. + + Arguments: + - column: The column to aggregate. + - operation: The name of the aggregation operation. + - name_suffix: The suffix to apply to the name of the aggregate column. + - new_type: The SQL type of the result column. +make_aggregate : Column -> Text -> Text -> Sql_Type -> Column make_aggregate column operation name_suffix="_agg" new_type=Nothing = actual_new_type = if new_type.is_nothing then column.sql_type else new_type expr = IR.Operation operation [column.expression] diff --git a/distribution/std-lib/Standard/src/Database/Data/Dialect.enso b/distribution/std-lib/Standard/src/Database/Data/Dialect.enso index 43e350e259..73274ce5e4 100644 --- a/distribution/std-lib/Standard/src/Database/Data/Dialect.enso +++ b/distribution/std-lib/Standard/src/Database/Data/Dialect.enso @@ -15,14 +15,14 @@ type Dialect Represents a specific SQL dialect. - It encapsulates dialect-specific code generation details allowing us to - support differing SQL dialects. - Arguments: - name: name of the dialect. - generate_sql: a function which generates SQL code from the internal representation according to the specific dialect. - # type Dialect (name : Text) (generate_sql : Query -> Sql.Statement) + + It encapsulates dialect-specific code generation details allowing us to + support differing SQL dialects. + # type Dialect (name : Text) (generate_sql : Query -> Sql.Statement) type Dialect name generate_sql ## PRIVATE @@ -98,5 +98,7 @@ sqlite = Dialect "sqlite" (query -> Base_Generator.generate_query dialect query . build) ## PRIVATE + + A vector of SQL dialects supported by the Database library. supported_dialects : Vector Dialect supported_dialects = [here.postgresql, here.sqlite] diff --git a/distribution/std-lib/Standard/src/Database/Data/Internal/Base_Generator.enso b/distribution/std-lib/Standard/src/Database/Data/Internal/Base_Generator.enso index 15f3085c8a..d3c081b136 100644 --- a/distribution/std-lib/Standard/src/Database/Data/Internal/Base_Generator.enso +++ b/distribution/std-lib/Standard/src/Database/Data/Internal/Base_Generator.enso @@ -6,19 +6,21 @@ import Standard.Database.Data.Internal.IR from Standard.Database.Data.Sql import Sql_Type type Internal_Dialect + ## PRIVATE An internal representation of a SQL dialect. Arguments: - - operation_map: the mapping which maps operation names to their + - operation_map: The mapping which maps operation names to their implementations; each implementation is a function which takes SQL builders for the arguments and should return a builder yielding the whole operation. - - wrap_identifier: a function that converts an arbitrary supported + - wrap_identifier: A function that converts an arbitrary supported identifier name in such a way that it can be used in the query; that usually consists of wrapping the name in quotes and escaping any quotes within it. + # type Internal_Dialect (operation_map : Map Text (Vector Sql.Builder -> Sql.Builder)) # (identifier_wrapper : Text -> Sql.Builder) type Internal_Dialect operation_map wrap_identifier @@ -27,7 +29,9 @@ type Internal_Dialect Creates a copy of the dialect that supports additional operations or overrides existing ones. + # extend_with : Vector [Text, Vector Sql.Builder -> Sql.Builder] -> Internal_Dialect + extend_with : Vector -> Internal_Dialect extend_with mappings = new_map = mappings.fold this.operation_map (m -> el -> m.insert (el.at 0) (el.at 1)) Internal_Dialect new_map this.wrap_identifier @@ -35,6 +39,9 @@ type Internal_Dialect ## PRIVATE A helper function to create a binary operator. + + Arguments: + - name: The name of the binary operator. make_binary_op : Text -> Vector Sql.Builder -> Sql.Builder make_binary_op name = arguments -> @@ -48,6 +55,9 @@ make_binary_op name = ## PRIVATE A helper function to create a unary operator. + + Arguments: + - name: The name of the unary operator. make_unary_op : Text -> Vector Sql.Builder -> Sql.Builder make_unary_op name = arguments -> @@ -61,6 +71,9 @@ make_unary_op name = A helper function to create a unary operator which is added to the right of the expression. + + Arguments: + - name: The name of the unary operator. make_right_unary_op : Text -> Vector Sql.Builder -> Sql.Builder make_right_unary_op name = arguments -> @@ -73,6 +86,9 @@ make_right_unary_op name = ## PRIVATE A helper function to create a functional operation. + + Arguments: + - name: The name of the function. make_function : Text -> Vector Sql.Builder -> Sql.Builder make_function name = arguments -> @@ -81,6 +97,9 @@ make_function name = ## PRIVATE A helper function to create an operation that takes no arguments. + + Arguments: + - code: The code for the constant. make_constant : Text -> Vector Sql.Builder -> Sql.Builder make_constant code = arguments -> @@ -90,8 +109,13 @@ make_constant code = ## PRIVATE Wraps the identifier name in quotes and escapes any quotes within the name - with double-quote. This is the simplest way of escaping identifiers that - should work across most dialects. + with double-quote. + + Arguments: + - identifier: The identifier to wrap and escape. + + This is the simplest way of escaping identifiers that should work across most + dialects. wrap_in_quotes : Text -> Sql.Builder wrap_in_quotes identifier = escaped = identifier.replace '"' '""' @@ -118,6 +142,10 @@ base_dialect = ## PRIVATE Builds code for an expression. + + Arguments: + - dialect: The SQL dialect in which the expression is being generated. + - expr: The expression to generate SQL code for. generate_expression : Internal_Dialect -> IR.Expression -> Sql.Builder generate_expression dialect expr = case expr of IR.Column origin name -> @@ -133,6 +161,10 @@ generate_expression dialect expr = case expr of Adds an alias for the expression, applicable for expressions that represent columns or sub-queries. + + Arguments: + - dialect: The dialect for which to add the alias. + - name: The name of the alias. alias : Internal_Dialect -> Text -> Sql.Builder alias dialect name = wrapped = dialect.wrap_identifier name @@ -141,6 +173,10 @@ alias dialect name = ## PRIVATE Builds code for the FROM clause. + + Arguments: + - dialect: The SQL dialect for which the code is generated. + - from_spec: A description of the FROM clause. generate_from_part : Internal_Dialect -> From_Spec -> Sql.Builder generate_from_part dialect from_spec = case from_spec of IR.From_Table name as_name -> @@ -162,7 +198,13 @@ generate_from_part dialect from_spec = case from_spec of ## PRIVATE Builds code for an ordering. + + Arguments: + - dialect: The SQL dialect for which the code is generated. + - order_description: A description of the ORDER clause. + # generate_order : Internal_Dialect -> [Expression, IR.Order_Direction, IR.Nulls_Order] -> Sql.Builder +generate_order : Internal_Dialect -> Vector -> Sql.Builder generate_order dialect order_description = order_suffix = case order_description.second of IR.Ascending -> Sql.code " ASC" @@ -173,6 +215,12 @@ generate_order dialect order_description = (here.generate_expression dialect (order_description.first)) ++ order_suffix ++ nulls_suffix ## PRIVATE + + Generates SQL code corresponding to a SELECT statement. + + Arguments: + - dialect: The SQL dialect for which the code is being generated. + - ctx: A description of the SELECT clause. generate_select_context : Internal_Dialect -> IR.Context -> Sql.Builder generate_select_context dialect ctx = gen_exprs exprs = exprs.map (here.generate_expression dialect) @@ -188,6 +236,15 @@ generate_select_context dialect ctx = (Sql.code " FROM ") ++ from_part ++ where_part ++ group_part ++ order_part ++ limit_part ## PRIVATE + + Generates the SQL code corresponding to an INSERT query. + + Arguments: + - dialect: The SQL dialect for which the code is being generated. + - table_name: The name of the table into which the values are being inserted. + - pairs: The values to insert into the table, consisting of pairs of key, and + expression returning a value. +generate_insert_query : Internal_Dialect -> Text -> Vector -> Sql.Builder generate_insert_query dialect table_name pairs = names = Sql.join ", " <| pairs.map (.first >> dialect.wrap_identifier) values = Sql.join ", " <| pairs.map (.second >> here.generate_expression dialect) @@ -198,6 +255,10 @@ generate_insert_query dialect table_name pairs = ## PRIVATE Builds code for a whole query. + + Arguments: + - dialect: The SQL dialect for which the code is being generated. + - query: An IR describing the query. generate_query : Internal_Dialect -> IR.Query -> Sql.Builder generate_query dialect query = case query of IR.Select columns ctx -> diff --git a/distribution/std-lib/Standard/src/Database/Data/Internal/Helpers.enso b/distribution/std-lib/Standard/src/Database/Data/Internal/Helpers.enso index f00f362c52..9fceaaa0b1 100644 --- a/distribution/std-lib/Standard/src/Database/Data/Internal/Helpers.enso +++ b/distribution/std-lib/Standard/src/Database/Data/Internal/Helpers.enso @@ -10,6 +10,10 @@ polyglot java import java.util.regex.Pattern Checks if the two tables or columns have the same context and use the same connection. + Arguments: + - entity1: The entity to check against the second. + - entity2: The entity to check against the first. + To combine different objects they need to satisfy this requirement, otherwise the combination would be ill-formed. check_integrity : (Table | Column) -> (Table | Column) -> Boolean @@ -20,9 +24,13 @@ check_integrity entity1 entity2 = ## PRIVATE - A helper function simplifying argument handling. It always returns a vector, - if the argument was already a vector, it is kept as-is, otherwise it is - wrapped in a singleton vector. + A helper function simplifying argument handling. + + Arguments: + - x: A value that may or may not be a vector. + + It always returns a vector, if the argument was already a vector, it is kept + as-is, otherwise it is wrapped in a singleton vector. unify_vector_singleton : (Any | Vector.Vector Any) -> Vector.Vector Any unify_vector_singleton x = case x of Vector.Vector _ -> x @@ -32,14 +40,25 @@ unify_vector_singleton x = case x of Signals that a name for a column or table is not supported. + Arguments: + - text: The name that is not supported. + Currently the names can only include ASCII letters, numbers and the underscore. This is a temporary limitation simplifying name handling. It will be removed in a future version. type Unsupported_Name_Error text +Unsupported_Name_Error.to_display_text : Text +Unsupported_Name_Error.to_display_text = + "The name " + this.text + " is not currently supported by the Database library." + ## PRIVATE This is used to check if the new name is safe for use in Sql queries. + + Arguments: + - name: The name to check for safety. + In a future version we will decouple the internal Sql-safe names from the external names shown to the user, but as a temporary solution we only allow Sql-safe names for columns. diff --git a/distribution/std-lib/Standard/src/Database/Data/Internal/IR.enso b/distribution/std-lib/Standard/src/Database/Data/Internal/IR.enso index 6cfa4602a8..1a190b8323 100644 --- a/distribution/std-lib/Standard/src/Database/Data/Internal/IR.enso +++ b/distribution/std-lib/Standard/src/Database/Data/Internal/IR.enso @@ -6,6 +6,7 @@ from Standard.Base import all reference, an interpolated constant or an operation that combines other expressions. type Expression + ## PRIVATE The internal representation of an SQL expression that gets a value from a @@ -16,7 +17,7 @@ type Expression originates from, it corresponds to the `alias` field in `from_spec`. - name: the name of the column directly in the table or its alias in a sub-query. - # type Column (origin : Text) (name : Text) + # type Column (origin : Text) (name : Text) type Column origin name ## PRIVATE @@ -50,9 +51,19 @@ type Internal_Column ## PRIVATE An internal column structure. + + Arguments: + - name: The column name. + - sql_type: The SQL type of the column. + - expression: An expression for applying to the column. type Internal_Column name sql_type expression ## PRIVATE + + Rename the internal column. + + Arguments: + - new_name: The new name for the column. rename : Text -> Internal_Column rename new_name = Internal_Column new_name this.sql_type this.expression @@ -83,15 +94,18 @@ type Context - meta_index: a list of internal columns to use for joining or grouping. - limit: an optional maximum number of elements that the equery should return. - # type Context (from_spec : From_Spec) (where_filters : Vector Expression) - # (orders : Vector [Expression, Order_Direction, Nulls_Order]) - # (groups : Vector Expression) (meta_index : Vector Internal_Column) - # (limit : Nothing | Integer) + # type Context (from_spec : From_Spec) (where_filters : Vector Expression) + # (orders : Vector [Expression, Order_Direction, Nulls_Order]) + # (groups : Vector Expression) (meta_index : Vector Internal_Column) + # (limit : Nothing | Integer) type Context from_spec where_filters orders groups meta_index limit ## PRIVATE Returns a copy of the context with changed `meta_index`. + + Arguments: + - new_index: The new index to set in the query. set_index : Vector Internal_Column -> Context set_index new_index = Context this.from_spec this.where_filters this.orders this.groups new_index this.limit @@ -99,6 +113,9 @@ type Context ## PRIVATE Returns a copy of the context with changed `where_filters`. + + Arguments: + - new_filters: The new filters to set in the query. set_where_filters : Vector Expression -> Context set_where_filters new_filters = Context this.from_spec new_filters this.orders this.groups this.meta_index this.limit @@ -106,13 +123,20 @@ type Context ## PRIVATE Returns a copy of the context with changed `orders`. - # set_orders : Vector [Expression, Order_Direction] -> Context + + Arguments: + - new_orders: The new ordering clauses to set in the query. + # set_orders : Vector [Expression, Order_Direction] -> Context + set_orders : Vector -> Context set_orders new_orders = Context this.from_spec this.where_filters new_orders this.groups this.meta_index this.limit ## PRIVATE Returns a copy of the context with changed `groups`. + + Arguments: + - new_groups: The new grouping clauses to set in the query. set_groups : Vector Expression -> Context set_groups new_groups = Context this.from_spec this.where_filters this.orders new_groups this.meta_index this.limit @@ -120,6 +144,9 @@ type Context ## PRIVATE Returns a copy of the context with changed `limit`. + + Arguments: + - new_limit: The new limit clauses to set in the query. set_limit : (Nothing | Integer) -> Context set_limit new_limit = Context this.from_spec this.where_filters this.orders this.groups this.meta_index new_limit @@ -139,6 +166,7 @@ type Context This is useful as a preprocessing step between combining queries, for example in a join. # as_subquery : Text -> Vector (Vector Internal_Column) -> [IR.Sub_Query, Vector (Vector Internal_Column)] + as_subquery : Text -> Vector -> Vector as_subquery alias column_lists = rewrite_internal_column : Internal_Column -> Internal_Column rewrite_internal_column column = @@ -169,7 +197,7 @@ type From_Spec parts of the query, this is especially useful for example in self-joins, allowing to differentiate between different instances of the same table. - # type From_Table (table_name : Text) (alias : Text) + # type From_Table (table_name : Text) (alias : Text) type From_Table table_name alias ## PRIVATE @@ -183,8 +211,8 @@ type From_Spec - on: a list of expressions that will be used as join conditions, these are usually be equalities between expressions from the left and right sources. - # type Join (kind : Join_Kind) (left_spec : From_Spec) - # (right_spec : From_Spec) (on : Vector Expression) + # type Join (kind : Join_Kind) (left_spec : From_Spec) + # (right_spec : From_Spec) (on : Vector Expression) type Join kind left_spec right_spec on ## PRIVATE @@ -285,16 +313,19 @@ type Query A Select SQL query. Arguments: - - expressions: list of pairs specifying the columns to materialize; each + - expressions: List of pairs specifying the columns to materialize; each is a pair whose first element is the name of the materialized column and the second element is the expression to compute. - - context: the query context, see `Context` for more detail. + - context: The query context, see `Context` for more detail. # type Select (expressions : [Text, Expression]) (context : Context) type Select columns context ## PRIVATE A Select SQL query that gets all columns in a table. + + Arguments: + - context: The query context, see `Context` for more detail. type Select_All context ## PRIVATE @@ -302,14 +333,17 @@ type Query An Insert SQL query that inserts a single row to the table. Arguments: - - table_name: name of the table to insert to. - - pairs: a list of pairs consisting of a column name and and expression. + - table_name: The name of the table to insert to. + - pairs: A list of pairs consisting of a column name and and expression. type Insert table_name pairs ## PRIVATE Creates a query context that just fetches data from a table, without any additional processing. + + Arguments: + - table_name: The name of the tanle for which the context is being created. make_ctx_from : Text -> Context make_ctx_from table_name = Context (From_Table table_name table_name) [] [] [] [] Nothing @@ -317,15 +351,25 @@ make_ctx_from table_name = ## PRIVATE Creates an expression which is a simple constant to be interpolated. + + Arguments: + - sql_type: The SQL type of the value. + - x: The value to turn into a constant. make_constant : Sql.Sql_Type -> Any -> Expression make_constant sql_type x = Constant sql_type x ## PRIVATE - A helper function to subsitute names tables inside of expressions. It is used - for example when renaming a table during a join. -substitute_origin : Text -> Text -> Expression + A helper function to subsitute names tables inside of expressions. + + Arguments: + - old_origin: The old table name. + - new_origin: The new table name. + - expr: The expression in which the substitution should be performed. + + It is used for example when renaming a table during a join. +substitute_origin : Text -> Text -> Expression -> Expression substitute_origin old_origin new_origin expr = case expr of Column origin name -> if origin == old_origin then Column new_origin name else expr @@ -338,6 +382,10 @@ substitute_origin old_origin new_origin expr = case expr of Lifts a function mapping expressions into a function mapping internal columns which applies the original function to their expressions, leaving other fields as-is. + + Arguments: + - f: The function to map over expressions. + - col: The column over which to apply `f`. lift_expression_map : (Expression -> Expression) -> Internal_Column -> Internal_Column lift_expression_map f col = Internal_Column col.name col.sql_type (f col.expression) diff --git a/distribution/std-lib/Standard/src/Database/Data/Internal/Vector_Builder.enso b/distribution/std-lib/Standard/src/Database/Data/Internal/Vector_Builder.enso index 99be0b6184..6fa8dfb897 100644 --- a/distribution/std-lib/Standard/src/Database/Data/Internal/Vector_Builder.enso +++ b/distribution/std-lib/Standard/src/Database/Data/Internal/Vector_Builder.enso @@ -11,10 +11,23 @@ from Builtins import Array is known in advance and the tree is traversed in order to create the resulting vector without resizing it. type Vector_Builder + ## PRIVATE + + A leaf in the vector builder. + + Arguments: + - vec: The vector at the leaf. type Leaf vec ## PRIVATE + + A node that appends the two child nodes. + + Arguments: + - left: The left subtree. + - right: The right subtree. + - len: The length of the vectors across the subtrees. type Append left right len ## PRIVATE @@ -52,6 +65,9 @@ type Vector_Builder Concatenates another builder or vector to this. + Arguments: + - other: The other vector to concatenate with `this`. + It returns a new builder that will yield a vector that is a concatenation of `this` and the argument. ++ : Vector_Builder Any | Vector Any -> Vector_Builder Any @@ -71,5 +87,8 @@ empty = Leaf [] ## PRIVATE Creates a vector builder from a vector. + + Arguments: + - vec: The vector to create a vector builder from. from_vector : Vector Any -> Vector_Builder Any from_vector vec = Leaf vec diff --git a/distribution/std-lib/Standard/src/Database/Data/Sql.enso b/distribution/std-lib/Standard/src/Database/Data/Sql.enso index cb77b3a744..a9a27928e6 100644 --- a/distribution/std-lib/Standard/src/Database/Data/Sql.enso +++ b/distribution/std-lib/Standard/src/Database/Data/Sql.enso @@ -4,8 +4,54 @@ import Standard.Database.Data.Internal.Vector_Builder polyglot java import java.sql.Types +## UNSTABLE + + Creates a Builder representing and empty code fragment. +empty : Builder +empty = Builder (Vector_Builder.empty) + +## UNSTABLE + + Creates a Builder representing a code fragment containing the specified raw + code. + + Arguments: + - text: The raw SQL code. +code : Text -> Builder +code text = + vec = if text.is_empty then [] else [Sql_Code_Part text] + Builder (Vector_Builder.from_vector vec) + +## UNSTABLE + + Creates a Builder representing an interpolation of the given object. + + Arguments: + - sql_type: The expected SQL type of `object`. + - object: The object to be interpolated into the query as if it has the type + given by `sql_type`. +interpolation : Sql_Type -> Any -> Builder +interpolation sql_type object = Builder (Vector_Builder.from_vector [Sql_Interpolation sql_type object]) + +## UNSTABLE + + Joins a vector of code fragments with the provided separator. + + Arguments: + - separator: The separator to use when joining the code fragments. + - statements: The SQL statements to join using `separator`. +join : Builder | Text -> Vector Builder -> Builder +join separator statements = + sep = case separator of + Builder _ -> separator + _ -> here.code separator + + if statements.length == 0 then here.empty else + (1.up_to statements.length . fold (statements.at 0) acc-> i-> acc ++ sep ++ statements.at i) + ## Represents an internal SQL data-type. type Sql_Type + ## Represents an internal SQL data-type. Arguments: @@ -35,24 +81,29 @@ type Sql_Type ## PRIVATE - Returns True if this type represents an integer. It only handles the - standard types so it may return false negatives for non-standard ones. + Returns True if this type represents an integer. + + It only handles the standard types so it may return false negatives for + non-standard ones. is_definitely_integer : Boolean is_definitely_integer = [Types.INTEGER, Types.SMALLINT, Types.TINYINT].contains this.typeid ## PRIVATE - Returns True if this type represents a boolean. It only handles the - standard types so it may return false negatives for non-standard ones. + Returns True if this type represents a boolean. + + It only handles the standard types so it may return false negatives for + non-standard ones. is_definitely_boolean : Boolean is_definitely_boolean = [Types.BOOLEAN, Types.BIT].contains this.typeid ## PRIVATE - Returns True if this type represents a floating point number. It only - handles the standard types so it may return false negatives for + Returns True if this type represents a floating point number. + + It only handles the standard types so it may return false negatives for non-standard ones. is_definitely_double : Boolean is_definitely_double = @@ -67,35 +118,51 @@ type Sql_Type ## UNSTABLE A fragment of a SQL query. + It can either be a Sql_Code_Part that represents raw SQL code or Sql_Interpolation which represents an object that will be interpolated into the query. type Sql_Fragment + ## UNSTABLE A SQL fragment that represents raw SQL code. - # type Sql_Code_Part (code : Text) + + Arguments: + - code: A fragment of SQL code. + # type Sql_Code_Part (code : Text) type Sql_Code_Part code + ## UNSTABLE A SQL fragment that represents an object which will be interpolated into the query. - # type Sql_Interpolation (sql_type : Sql_Type) (object : Any) + + Arguments: + - sql_type: The expected SQL type of `object`. + - object: A value that will be interpolated into the query, interpreted + as having the type `sql_type`. + # type Sql_Interpolation (sql_type : Sql_Type) (object : Any) type Sql_Interpolation sql_type object type Statement + ## UNSTABLE Represents a built SQL statement. + Arguments: + - internal_fragments: A vector of SQL code fragments. + The statement consists of SQL code with parameters and values that will be interpolated for these parameters. - # type Statement (internal_fragments : Vector Sql_Fragment) + # type Statement (internal_fragments : Vector Sql_Fragment) type Statement internal_fragments ## UNSTABLE A vector of code fragments. + Consists of two types of values: - Sql_Code_Part, representing parts of raw SQL code and - Sql_Interpolation, representing objects that will be interpolated in @@ -129,7 +196,7 @@ type Statement Returns a pair consisting of the SQL code with holes for values and a list for values that should be substituted. - # prepare : [Text, Vector Any] + # prepare : [Text, Vector Any] prepare = to_code fragment = case fragment of Sql_Code_Part code -> code @@ -155,18 +222,25 @@ type Statement Json.from_pairs [["query", fragments]] type Builder - ## UNSTABLE + + ## PRIVATE A Builder for SQL queries. - It can be used to concatenate parts of SQL code in O(1) time and at the end - build the actual query in linear time. + Arguments: + - fragments: A builder that contains fragments of SQL code. + + It can be used to concatenate parts of SQL code in O(1) time and at the + end build the actual query in linear time. # type Builder (fragments : Vector_Builder.Vector_Builder Sql_Fragment) type Builder fragments ## UNSTABLE Concatenates two code fragments. + + Arguments: + - other: The code fragment to append to `this`. ++ : Builder -> Builder ++ other = Builder (this.fragments ++ other.fragments) @@ -196,6 +270,10 @@ type Builder ## UNSTABLE If the fragment is non empty, prepends the specified prefix to it. + + Arguments: + - prefix: The prefix to append if the fragment is present. + Empty fragments are unaffected. prefix_if_present : Text | Builder -> Builder prefix_if_present prefix = @@ -204,43 +282,13 @@ type Builder _ -> here.code prefix if this.is_empty then this else pref++this -## UNSTABLE - - Creates a Builder representing and empty code fragment. -empty : Builder -empty = Builder (Vector_Builder.empty) - -## UNSTABLE - - Creates a Builder representing a code fragment containing the specified raw - code. -code : Text -> Builder -code text = - vec = if text.is_empty then [] else [Sql_Code_Part text] - Builder (Vector_Builder.from_vector vec) - -## UNSTABLE - - Creates a Builder representing an interpolation of the given object. -interpolation : Sql_Type -> Any -> Builder -interpolation sql_type object = Builder (Vector_Builder.from_vector [Sql_Interpolation sql_type object]) - -## UNSTABLE - - Joins a vector of code fragments with the provided separator. -join : Builder | Text -> Vector Builder -> Builder -join separator statements = - sep = case separator of - Builder _ -> separator - _ -> here.code separator - - if statements.length == 0 then here.empty else - (1.up_to statements.length . fold (statements.at 0) acc-> i-> acc ++ sep ++ statements.at i) - -## UNSTABLE +## PRIVATE Merges neighboring code fragments to create a more compact representation of the same code. + + Arguments: + - fragments: The fragments to be merged together. optimize_fragments : Vector Sql_Fragment -> Vector Sql_Fragment optimize_fragments fragments = builder = Vector.new_builder diff --git a/distribution/std-lib/Standard/src/Database/Data/Table.enso b/distribution/std-lib/Standard/src/Database/Data/Table.enso index 5fb14a3d82..6d3f5501b0 100644 --- a/distribution/std-lib/Standard/src/Database/Data/Table.enso +++ b/distribution/std-lib/Standard/src/Database/Data/Table.enso @@ -16,12 +16,19 @@ polyglot java import java.sql.JDBCType ## Represents a column-oriented table data structure backed by a database. type Table + ## PRIVATE Represents a column-oriented table data structure backed by a database. - # type Table (name : Text) (connection : Connection) - # (internal_columns : Vector Internal_Column) - # (context : IR.Context) + + Arguments: + - name: The name of the table. + - connection: The connection with whicg the table is associated. + - internal_columns: The internal representation of the table columns. + - context: The context associated with this table. + # type Table (name : Text) (connection : Connection) + # (internal_columns : Vector Internal_Column) + # (context : IR.Context) type Table name connection internal_columns context ## UNSTABLE @@ -50,7 +57,7 @@ type Table ## UNSTABLE - Converts this table to a JSON structure. + Converts this table into a JSON structure. to_json : Json to_json = case this.internal_columns.is_empty of True -> @@ -60,15 +67,23 @@ type Table ## UNSTABLE Returns the column with the given name. - at : Text -> Column ! UnknownColumnError + + Arguments: + - name: The name of the column to get. + at : Text -> Column ! No_Such_Column_Error at name = internal = this.internal_columns.find (p -> p.name == name) this.make_column internal . map_error (_ -> No_Such_Column_Error name) ## PRIVATE - Resolves the column name to a column within this table. If instead of a - name, a column is provided, it is returned as-is as long as it comes from - the same context. + + Resolves the column name to a column within this table. + + Arguments: + - column: The name (or column handle) for the column you want to resolve. + + If instead of a name, a column is provided, it is returned as-is as long + as it comes from the same context. resolve : Text | Column -> Column resolve column = case column of Text -> Panic.rethrow (this.at column) @@ -80,7 +95,13 @@ type Table Selects only the rows of this table that correspond to `True` values in `filter`. + + Arguments: + - filter: A column of boolean values that will be used to mask the table + rows. + This is useful for filtering the rows by given predicate. + > Example Select only the rows of `my_table` where the `"Status"` column has the value `"Valid"` @@ -100,6 +121,9 @@ type Table Returns a new Table that will include at most `max_rows` rows from the original Table. + Arguments: + - max_rows: The maximum number of rows to get from the table. + Since this Table is backed by an SQL database, the Table returned by the `limit` method is deterministic only if the Table has been ordered (using the `sort` method). @@ -129,8 +153,14 @@ type Table ## UNSTABLE - Sets the column value at the given name. If a column with the given name - already exists, it will be replaced. Otherwise a new column is added. + Sets the column value at the given name. + + Arguments: + - name: The name of the column to set. + - column: The new value for the column called `name`. + + If a column with the given name already exists, it will be replaced. + Otherwise a new column is added. set : Text -> Column -> Table set name column = case Helpers.ensure_name_is_sane name of True -> @@ -156,6 +186,9 @@ type Table ## UNSTABLE Sets the index of this table, using the column with the provided name. + + Arguments: + - index: The column to use as the index of the table. set_index : Text | Column | Vector Text -> Table set_index index = Panic.recover <| new_index = (Helpers.unify_vector_singleton index).map (this.at >> .as_internal) @@ -174,7 +207,9 @@ type Table ## UNSTABLE - Returns the index (or indexes) of this table, as a column (indexed by itself). + Returns the index (or indexes) of this table, as a column (indexed by + itself). + Throws `No_Index_Set_Error` if there is no index set. index : Column | Vector Column ! Materialized_Table.No_Index_Set_Error index = @@ -188,26 +223,26 @@ type Table Sorts the table according to the specified rules. Arguments: - - by: specifies the columns used for reordering the table. This - argument may be one of: - - a text: the text is treated as a column name. - - a column: any column, which is an expression computed from this - table. - - an order rule: specifies both the sorting column and additional - settings, that will take precedence over the global parameters of - this sort operation. The `column` field of the rule may be a text - or a column, with the semantics described above. - - a vector of any of the above: this will result in a hierarchical - sorting, such that the first rule is applied first, the second is - used for breaking ties, etc. - - order: specifies the default sort order for this operation. All the - rules specified in the `by` argument will default to this setting, - unless specified in the rule. - - missing_last: specifies the default placement of missing values when - compared to non-missing ones. This setting may be overriden by the - particular rules of the `by` argument. Note thet this argument is - independent from `order`, i.e. missing values will always be sorted - according to this rule, ignoring the ascending / descending setting. + - by: Specifies the columns used for reordering the table. This + argument may be one of: + - a text: The text is treated as a column name. + - a column: Any column, which is an expression computed from this + table. + - an order rule: Specifies both the sorting column and additional + settings, that will take precedence over the global parameters of + this sort operation. The `column` field of the rule may be a text + or a column, with the semantics described above. + - a vector of any of the above: This will result in a hierarchical + sorting, such that the first rule is applied first, the second is + used for breaking ties, etc. + - order: Specifies the default sort order for this operation. All the + rules specified in the `by` argument will default to this setting, + unless specified in the rule. + - missing_last: Specifies the default placement of missing values when + compared to non-missing ones. This setting may be overriden by the + particular rules of the `by` argument. Note thet this argument is + independent from `order`, i.e. missing values will always be sorted + according to this rule, ignoring the ascending / descending setting. > Example Sorting `table` in ascending order by the value in column `'Quantity'` @@ -261,6 +296,9 @@ type Table ## UNSTABLE Selects a subset of columns from this table by name. + + Arguments: + - columns: The names of the columns to select from the table. select : Vector Text -> Table select columns = find_col = (name -> this.internal_columns.find (p -> p.name == name)) @@ -271,21 +309,21 @@ type Table Efficiently joins two tables based on either the index or a key column. + Arguments: + - other: the table being the right operand of this join operation. + - on: the column(s) or expression(s) of `this` that should be used as + the join key. If this argument is not provided, the index of `this` + will be used. + - drop_unmatched: whether the rows of `this` without corresponding + matches in `other` should be dropped from the result. + - left_suffix: a suffix that should be added to the columns of `this` + when there's a name conflict with a column of `other`. + - right_suffix: a suffix that should be added to the columns of `other` + when there's a name conflict with a column of `this`. + The resulting table contains rows of `this` extended with rows of `other` with matching indexes. If the index in `other` is not unique, the corresponding rows of `this` will be duplicated in the result. - - Arguments: - - other: the table being the right operand of this join operation. - - on: the column(s) or expression(s) of `this` that should be used as - the join key. If this argument is not provided, the index of `this` - will be used. - - drop_unmatched: whether the rows of `this` without corresponding - matches in `other` should be dropped from the result. - - left_suffix: a suffix that should be added to the columns of `this` - when there's a name conflict with a column of `other`. - - right_suffix: a suffix that should be added to the columns of `other` - when there's a name conflict with a column of `this`. join : Table | Column -> Nothing | Text | Column | Vector (Text | Column) -> Boolean -> Text -> Text -> Table join other on=Nothing drop_unmatched=False left_suffix='_left' right_suffix='_right' = case other of Column _ _ _ _ _ -> this.join other.to_table on drop_unmatched left_suffix right_suffix @@ -365,7 +403,9 @@ type Table Returns an aggregate table resulting from grouping the elements by the value of the specified column. - If the `by` argument is not set, the index is used for grouping instead. + Arguments: + - by: The column names on which to group. If this is not set, the index + will be used for grouping instead. group : Vector Text | Text | Nothing -> Aggregate_Table group by=Nothing = Panic.recover <| cols = case by of @@ -481,6 +521,9 @@ type Table ## PRIVATE Helper to create columns from internal columns. + + Arguments: + - internal: The internal column to use for creating a column. make_column : Internal_Column -> Column make_column internal = Column internal.name this.connection internal.sql_type internal.expression this.context @@ -488,11 +531,19 @@ type Table ## PRIVATE Returns a copy of this table with updated internal columns. + + Arguments: + - columns: The columns with which to update this table. + updated_columns : Vector Colums -> Table updated_columns columns = Table this.name this.connection columns this.context ## PRIVATE Returns a copy of this table with updated context. + + Arguments: + - ctx: The new context for this table. + updated_context : Context -> Table updated_context ctx = Table this.name this.connection this.internal_columns ctx ## PRIVATE @@ -506,12 +557,14 @@ type Table ## PRIVATE - Inserts a new row to the table. It actually modifies the underlying table - in the database. + Inserts a new row to the table. - It can only be called on the Table if no operations modifying it have - been performed like modifying, removing or adding columns, filtering, - grouping etc. + Arguments: + - values: The values making up the row of the table. + + It actually modifies the underlying table in the database. It can only + be called on the Table if no operations modifying it have been performed + like modifying, removing or adding columns, filtering, grouping etc. insert : Vector Any -> Nothing insert values = table_name = case this.context.from_spec of @@ -533,9 +586,15 @@ type Aggregate_Table ## UNSTABLE Represents a table with grouped rows. - # type Aggregate_Table (name : Text) (connection : Connection) - # (internal_columns : Vector [Text, IR.Expression]) - # (context : IR.Context) + + Arguments: + - name: The name of the table. + - connection: The connection with whicg the table is associated. + - internal_columns: The internal representation of the table columns. + - context: The context associated with this table. + # type Aggregate_Table (name : Text) (connection : Connection) + # (internal_columns : Vector [Text, IR.Expression]) + # (context : IR.Context) type Aggregate_Table name connection internal_columns context ## UNSTABLE @@ -555,6 +614,9 @@ type Aggregate_Table ## UNSTABLE Returns an aggregate column with the given name, contained in this table. + + Arguments: + - name: The name of the aggregate column to get from the aggregate table. at : Text -> Column ! No_Such_Column_Error at name = internal = this.internal_columns.find (p -> p.name == name) @@ -563,7 +625,10 @@ type Aggregate_Table ## PRIVATE Helper to create aggregate columns from internal columns. - # make_column : Internal_Column -> Aggregate_Column + + Arguments: + - internal: The internal column to make into an aggregate column. + make_column : Internal_Column -> Aggregate_Column make_column internal = Aggregate_Column internal.name this.connection internal.sql_type internal.expression this.context @@ -579,6 +644,7 @@ type Aggregate_Table Table this.name this.connection new_cols new_ctx type Integrity_Error + ## UNSTABLE Signalizes that an operation tried using objects coming from different @@ -591,10 +657,19 @@ type Integrity_Error to_text : Text to_text = this.object_description + " comes from a different context." + to_display_text : Text + to_display_text = this.to_text + ## PRIVATE Creates a Table out of a connection, name and list of column names. - # make_table : Connection -> Text -> Vector [Text, Sql.Sql_Type] -> Table + + Arguments: + - connection: The connection to a database. + - table_name: The name of the table to get. + - columns: The names of the columns to get. +# make_table : Connection -> Text -> Vector [Text, Sql.Sql_Type] -> Table +make_table : Connection -> Text -> Vector -> Table make_table connection table_name columns = ctx = IR.make_ctx_from table_name cols = columns.map (p -> Internal_Column p.first p.second (IR.Column table_name p.first)) @@ -606,15 +681,15 @@ make_table connection table_name columns = contains a fragment of the underlying data and count of all rows. Arguments: - - df: the materialized dataframe that contains the data to be displayed, it + - df: The materialized dataframe that contains the data to be displayed, it should have no indices set. - - indices_count: indicates how many columns from the materialized dataframe + - indices_count: Indicates how many columns from the materialized dataframe should be treated as indices in the display (index columns will be bold if `format_terminal` is enabled). - - all_rows_count: the count of all rows in the underlying Table; if + - all_rows_count: The count of all rows in the underlying Table; if `all_rows_count` is bigger than the amount of rows of `df`, an additional line will be included that will say how many hidden rows there are. - - format_term: a boolean flag, specifying whether to use ANSI escape codes + - format_term: A boolean flag, specifying whether to use ANSI escape codes for rich formatting in the terminal. display_dataframe : Materialized_Table.Table -> Integer -> Integer -> Boolean -> Text display_dataframe df indices_count all_rows_count format_terminal = @@ -636,6 +711,12 @@ display_dataframe df indices_count all_rows_count format_terminal = Creates a list of non-colliding names by merging the two lists and appending suffixes if necessary. + Arguments: + - left_names: The names on the left. + - right_names: The names on the right. + - left_suffix: The suffix to apply to colliding names on the left. + - right_suffix: The suffix to apply to colliding names on the right. + If even after appending the suffixes it is impossible to have unique names, it throws a panic. It returns two vectors, one for each input. It assumes that the names within each argument itself are unique. @@ -668,9 +749,15 @@ combine_names left_names right_names left_suffix right_suffix = ## PRIVATE - Transforms `preferred_names` names in such a way to not collide with `used_names`. If a name - from `preferred_names` does not collide with others, it is kept as is, otherwise numerical - suffixes are added. + Transforms `preferred_names` names in such a way to not collide with + `used_names`. + + Arguments: + - used_names: The names that have already been used. + - preferred_names: The names that the user wants to use. + + If a name from `preferred_names` does not collide with others, it is kept as + is, otherwise numerical suffixes are added. fresh_names : Vector Text -> Vector Text -> Vector Text fresh_names used_names preferred_names = freshen currently_used name ix = @@ -686,7 +773,12 @@ fresh_names used_names preferred_names = ## PRIVATE - Transforms the vector of columns, changing names of each column to the corresponding name from the second vector. + Transforms the vector of columns, changing names of each column to the + corresponding name from the second vector. + + Arguments: + - columns: A vector of columns to rename. + - new_names: The new names for the columns. rename_columns : Vector Internal_Column -> Vector Text -> Vector Internal_Column rename_columns columns new_names = columns.zip new_names col-> name-> @@ -694,8 +786,15 @@ rename_columns columns new_names = ## PRIVATE - Ensures that the provided columns do not clash with the vector of names provided as first argument. - Original column names are kept if possible, but if they would clash, the columns are renamed. + Ensures that the provided columns do not clash with the vector of names + provided as first argument. + + Arguments: + - used_names: The already used names. + - columns: The columns to rename to avoid clashes. + + Original column names are kept if possible, but if they would clash, the + columns are renamed. freshen_columns : Vector Text -> Vector Column -> Vector Column freshen_columns used_names columns = fresh_names = here.fresh_names used_names (columns.map .name) diff --git a/distribution/std-lib/Standard/src/Geo/Geo_Json.enso b/distribution/std-lib/Standard/src/Geo/Geo_Json.enso index d45c5e70b1..ea620aeda0 100644 --- a/distribution/std-lib/Standard/src/Geo/Geo_Json.enso +++ b/distribution/std-lib/Standard/src/Geo/Geo_Json.enso @@ -6,9 +6,13 @@ from Standard.Base import all type Object_Type ## PRIVATE + + A Geo JSON feature. type Feature ## PRIVATE + + A Geo JSON feature collection. type Feature_Collection ## PRIVATE diff --git a/distribution/std-lib/Standard/src/Image/Codecs.enso b/distribution/std-lib/Standard/src/Image/Codecs.enso index 55c562decf..e27abf8898 100644 --- a/distribution/std-lib/Standard/src/Image/Codecs.enso +++ b/distribution/std-lib/Standard/src/Image/Codecs.enso @@ -30,7 +30,10 @@ type Write_Flag ## UNSTABLE - For a JPEG, this can be a quality from 0 to 100 (the higher, the better). + Sets the quality used when writing a JPEG. + + Arguments: + - value: A quality value from 0 to 100 (the higher, the better). type Write_Jpeg_Quality value=95 ## UNSTABLE @@ -45,25 +48,36 @@ type Write_Flag ## UNSTABLE - Separate luma quality level, 0 - 100. + Sets the luma quality level used when writing a JPEG. + + Arguments: + - value: A quality value from 0 to 100 (the higher, the better). type Write_Jpeg_Luma_Quality value=0 ## UNSTABLE - Separate chroma quality level, 0 - 100. + Sets the chroma quality level used when writing a JPEG. + + Arguments: + - value: A quality value from 0 to 100 (the higher, the better). type Write_Jpeg_Chroma_Quality value=0 ## UNSTABLE - For PNG, it can be the compression level from 0 to 9. A higher value - means a smaller size and longer compression time. + Sets the compression level used when writing a PNG. + + Arguments: + - value: A compression level from 0 to 9. A higher value means a smaller + size but a longer compression time. type Write_Png_Compression value=3 ## UNSTABLE - For WEBP, this is a quality from 1 to 100 (the higher, the better). - By default (without any parameter) and for quality above 100 the lossless - compression is used. + Sets the quality used when writing a WEBP image. + + Arguments: + - value: A quality from 0 to 100 (the higher, the better). A quality + above 100 indicates that the encoder should use lossless compression. type Write_Webp_Quality value=101 ## UNSTABLE @@ -74,8 +88,8 @@ type Write_Flag `Read_Alpha_Channel` flag is specified. Arguments: - - `location`: the file to read. - - `flags`: the read flags. + - location: the file to read. + - flags: the read flags. > Example Read the image. @@ -107,6 +121,10 @@ read location flags=[] = Write an image to a file. + Arguments: + - location: The location to write the image to. + - flags: A vector of flags that control how the image is written. + > Example Write the image with applying png compression. Codecs.write path image @@ -131,3 +149,4 @@ Image.Image.write location flags=[] = case e of Polyglot_Error _ -> Panic.throw (File.Io_Error ('Failed to write to the file at ' + path + '.')) err -> Panic.throw err + diff --git a/distribution/std-lib/Standard/src/Image/Data/Histogram.enso b/distribution/std-lib/Standard/src/Image/Data/Histogram.enso index 15a72a2e22..0472e8c937 100644 --- a/distribution/std-lib/Standard/src/Image/Data/Histogram.enso +++ b/distribution/std-lib/Standard/src/Image/Data/Histogram.enso @@ -11,6 +11,10 @@ type Histogram ## UNSTABLE The histogram of a single image channel. + + Arguments: + - channel: The channel in the image for which this is a histogram. + - data: The histogram data. type Histogram channel data ## UNSTABLE @@ -26,7 +30,7 @@ type Histogram Create a histogram for the specified channel of the image. Arguments: - `channel`: the channel number. + - channel: the channel number. > Example Create a histogram. diff --git a/distribution/std-lib/Standard/src/Image/Data/Image.enso b/distribution/std-lib/Standard/src/Image/Data/Image.enso index ef6a3cc016..72598a9efd 100644 --- a/distribution/std-lib/Standard/src/Image/Data/Image.enso +++ b/distribution/std-lib/Standard/src/Image/Data/Image.enso @@ -13,6 +13,9 @@ type Image The image data type. + Arguments: + - opencv_mat: The underlying matrix that stores the image data. + The image is represented with a matrix of rows x columns. Each pixel is represented with a vector of 1 to 4 values (channels). Pixel values are normalized in a range [0.0 .. 1.0]. @@ -41,8 +44,8 @@ type Image Get the pixel value indexed by row and column. Arguments: - - `row`: the row index. - - `column`: the column index. + - row: the row index. + - column: the column index. > Example Get the value at the specified row and column. @@ -61,11 +64,9 @@ type Image ## UNSTABLE Calculates the per-element sum of an image and a scalar or a matrix. - Matrix should have the same dimensions as the image. Arguments: - - - `value`: A value can be a number, a vector of numbers, or a matrix. The + - value: A value can be a number, a vector of numbers, or a matrix. The number value is applied to each pixel's channel of the image. The vector value is padded with zeros to match the number of channels and then applied to each image's pixel. The matrix value must have the same @@ -75,6 +76,8 @@ type Image appropriate pixel (the element with the same row and column) of this image. + The matrix should have the same dimensions as the image. + > Example Add the constant to an image. Operation will add 0.1 to each channel of the image. @@ -93,10 +96,9 @@ type Image ## UNSTABLE Calculates the per-element difference between an image and a scalar or a matrix. - Matrix should have the same dimensions as the image. Arguments: - - `value`: A value can be a number, a vector of numbers, or a matrix. The + - value: A value can be a number, a vector of numbers, or a matrix. The number value is applied to each pixel's channel of the image. The vector value is padded with zeros to match the number of channels and then applied to each image's pixel. The matrix value must have the same @@ -106,6 +108,8 @@ type Image appropriate pixel (the element with the same row and column) of this image. + The matrix should have the same dimensions as the image. + > Example Subtract 0.5 from each channel of the image. image - 0.5 @@ -123,10 +127,9 @@ type Image ## UNSTABLE Calculates the per-element product of an image and a scalar or a matrix. - Matrix should have the same dimensions as the image. Arguments: - - `value`: A value can be a number, a vector of numbers, or a matrix. The + - value: A value can be a number, a vector of numbers, or a matrix. The number value is applied to each pixel's channel of the image. The vector value is padded with zeros to match the number of channels and then applied to each image's pixel. The matrix value must have the same @@ -136,6 +139,8 @@ type Image appropriate pixel (the element with the same row and column) of this image. + The matrix should have the same dimensions as the image. + > Example Multiply each channel of the image by 2. image * 2 @@ -158,10 +163,9 @@ type Image ## UNSTABLE Performs per-element division of an image and a scalar or a matrix. - Matrix should have the same dimensions as the image. Arguments: - - `value`: A value can be a number, a vector of numbers, or a matrix. The + - value: A value can be a number, a vector of numbers, or a matrix. The number value is applied to each pixel's channel of the image. The vector value is padded with zeros to match the number of channels and then applied to each image's pixel. The matrix value must have the same @@ -171,6 +175,8 @@ type Image appropriate pixel (the element with the same row and column) of this image. + The matrix should have the same dimensions as the image. + > Example Divide each channel of the image by 2. image / 2 @@ -194,7 +200,7 @@ type Image Check the equality of two images. Arguments: - - `that`: the matrix to compare with. + - that: the matrix to compare with. ? Implementation Note Two images considered equal when they have the same number of rows, @@ -233,11 +239,12 @@ type Image Create an image from the array of values. Arguments: - - `values`: the vector of numbers. - - `rows`: the number of rows in the resulting image. - - `channels`: the number of channels in the resulting image. + - values: the vector of numbers. + - rows: the number of rows in the resulting image. + - channels: the number of channels in the resulting image. - The function expects the array of normalized values in a range of [0.0 .. 1.0]. + The function expects the array of normalized values to have each value in + the range of [0.0 .. 1.0]. > Example Create an image from the vector. diff --git a/distribution/std-lib/Standard/src/Image/Data/Image/Internal.enso b/distribution/std-lib/Standard/src/Image/Data/Image/Internal.enso index b8e11cebf4..5ad58af7af 100644 --- a/distribution/std-lib/Standard/src/Image/Data/Image/Internal.enso +++ b/distribution/std-lib/Standard/src/Image/Data/Image/Internal.enso @@ -8,6 +8,13 @@ polyglot java import org.opencv.core.Mat polyglot java import org.opencv.core.Scalar ## PRIVATE + + Apply a core matrix operation. + + Arguments: + - mat: The matrix to operate on. + - value: The value to apply to the matrix. + - function: The function with which to apply `value` to `mat`. core_op : Mat -> Any -> (Mat -> Scalar -> Mat -> Nothing) -> Nothing core_op mat value function = result = Mat.new @@ -22,6 +29,12 @@ core_op mat value function = Image.Image result ## PRIVATE + + Handles errors in `core_op`. + + Arguments: + - error: The value to throw as an error. +core_op_handler : Any core_op_handler error = case error of Matrix.Dimensions_Not_Equal -> Error.throw error diff --git a/distribution/std-lib/Standard/src/Image/Data/Matrix.enso b/distribution/std-lib/Standard/src/Image/Data/Matrix.enso index 0ee144d66b..b444f53c0d 100644 --- a/distribution/std-lib/Standard/src/Image/Data/Matrix.enso +++ b/distribution/std-lib/Standard/src/Image/Data/Matrix.enso @@ -12,13 +12,22 @@ type Matrix_Error ## UNSTABLE Indicates that a matrix has been accessed with an illegal index. + + Arguments: + - rows: The number of rows in the matrix. + - columns: The number of columns in the matrix. + - index: The requested index in the matrix. type Index_Out_Of_Bounds_Error rows columns index ## UNSTABLE - Indicates that operation has failed. + An error indicating that an operation has failed due to a mismatch of + matrix dimensions. type Dimensions_Not_Equal + ## UNSTABLE + + Pretty-prints a matrix error to be readable by the users. to_display_text : Text to_display_text = case this of Index_Out_Of_Bounds_Error rows columns index -> @@ -33,6 +42,9 @@ type Matrix The matrix data type. + Arguments: + - opencv_mat: The internal representation of the matrix. + Each value of the matrix is represented with an array of channels. In contrast to an Image data type, Matrix values are not normalized. @@ -59,8 +71,8 @@ type Matrix Get the matrix value at the specified row and column. Arguments: - - `row`: the row index. - - `column`: the column index. + - row: the row index. + - column: the column index. > Example Get the value at the specified row and column. @@ -81,8 +93,8 @@ type Matrix Reshape the matrix specifying new number of rows and channels. Arguments: - - `rows`: the new number of rows. - - `channels`: the new number of channels. + - rows: the new number of rows. + - channels: the new number of channels. > Example Reshape the matrix to a new shape of 3 rows and 1 column, with 1 channel. @@ -98,7 +110,7 @@ type Matrix Calculates the per-element sum of two matrices or a matrix and a scalar. Arguments: - - `value`: A value can be a number, a vector of numbers, or a matrix. The + - value: A value can be a number, a vector of numbers, or a matrix. The number value is applied to each values's channel of the matrix. The vector value is padded with zeros to match the number of channels and then applied to each pixel of this matrix. The matrix value must have @@ -124,10 +136,11 @@ type Matrix ## UNSTABLE - Calculates the per-element difference of two matrices or of a matrix and a scalar. + Calculates the per-element difference of two matrices or of a matrix and + a scalar. Arguments: - - `value`: A value can be a number, a vector of numbers, or a matrix. The + - value: A value can be a number, a vector of numbers, or a matrix. The number value is applied to each values's channel of the matrix. The vector value is padded with zeros to match the number of channels and then applied to each pixel of this matrix. The matrix value must have @@ -153,10 +166,11 @@ type Matrix ## UNSTABLE - Calculates the per-element product of two matrices or a matrix and a scalar. + Calculates the per-element product of two matrices or a matrix and a + scalar. Arguments: - - `value`: A value can be a number, a vector of numbers, or a matrix. The + - value: A value can be a number, a vector of numbers, or a matrix. The number value is applied to each values's channel of the matrix. The vector value is padded with zeros to match the number of channels and then applied to each pixel of this matrix. The matrix value must have @@ -190,7 +204,7 @@ type Matrix Performs per-element division of two matrices or a matrix and a scalar. Arguments: - - `value`: A value can be a number, a vector of numbers, or a matrix. The + - value: A value can be a number, a vector of numbers, or a matrix. The number value is applied to each values's channel of the matrix. The vector value is padded with zeros to match the number of channels and then applied to each pixel of this matrix. The matrix value must have @@ -219,7 +233,7 @@ type Matrix Check the equality of two matrices. Arguments: - - `that`: the matrix to compare with. + - that: the matrix to compare with. ? Implementation Note Two matrices considered equal when they have the same number of rows, @@ -234,8 +248,8 @@ type Matrix the matrix becomes `max_value`. Arguments: - - `min_value`: the minimum value in the resulting normalized range. - - `max_value`: the maximum value in the resulting normalized range. + - min_value: the minimum value in the resulting normalized range. + - max_value: the maximum value in the resulting normalized range. > Example Normalize a matrix from vector. @@ -277,9 +291,9 @@ type Matrix Create a matrix with all elements set to zero. Arguments: - - `rows`: the number of rows in the resulting matrix. - - `columns`: the number of columns in the resulitng matrix. - - `channels`: the number of channels in the resulting matrix. + - rows: the number of rows in the resulting matrix. + - columns: the number of columns in the resulitng matrix. + - channels: the number of channels in the resulting matrix. > Example Create a matrix. @@ -293,9 +307,9 @@ zeros rows columns channels=1 = Create a matrix with all elements set to one. Arguments: - - `rows`: the number of rows in the resulting matrix. - - `columns`: the number of columns in the resulitng matrix. - - `channels`: the number of channels in the resulting matrix. + - rows: the number of rows in the resulting matrix. + - columns: the number of columns in the resulitng matrix. + - channels: the number of channels in the resulting matrix. > Example Create a matrix. @@ -309,9 +323,9 @@ ones rows columns channels=1 = Create an identity matrix containing ones on a main diagonal. Arguments: - - `rows`: the number of rows in the resulting matrix. - - `columns`: the number of columns in the resulitng matrix. - - `channels`: the number of channels in the resulting matrix. + - rows: the number of rows in the resulting matrix. + - columns: the number of columns in the resulitng matrix. + - channels: the number of channels in the resulting matrix. > Example Create a matrix. @@ -325,9 +339,9 @@ identity rows columns channels=1 = Create a matrix from the provided vector. Arguments: - - `values`: the vector of numbers. - - `rows`: the number of rows in the resulting matrix. - - `channels`: the number of channels in the resulting matrix. + - values: the vector of numbers. + - rows: the number of rows in the resulting matrix. + - channels: the number of channels in the resulting matrix. > Example Create a matrix. @@ -335,3 +349,4 @@ identity rows columns channels=1 = from_vector : Vector -> Integer -> Integer -> Matrix from_vector values rows=1 channels=1 = Matrix (Java_Matrix.from_vector values.to_array channels rows) + diff --git a/distribution/std-lib/Standard/src/Image/Data/Matrix/Internal.enso b/distribution/std-lib/Standard/src/Image/Data/Matrix/Internal.enso index 6aa001510b..fa8c8aedae 100644 --- a/distribution/std-lib/Standard/src/Image/Data/Matrix/Internal.enso +++ b/distribution/std-lib/Standard/src/Image/Data/Matrix/Internal.enso @@ -7,6 +7,13 @@ polyglot java import org.opencv.core.Mat polyglot java import org.opencv.core.Scalar ## PRIVATE + + Apply a core matrix operation. + + Arguments: + - mat: The matrix to operate on. + - value: The value to apply to the matrix. + - function: The function with which to apply `value` to `mat`. core_op : Mat -> Any -> (Mat -> Scalar -> Mat -> Nothing) -> Nothing core_op mat value function = result = Mat.new @@ -21,6 +28,11 @@ core_op mat value function = Matrix.Matrix result ## PRIVATE + + Handles errors in `core_op`. + + Arguments: + - error: The value to throw as an error. core_op_handler error = case error of Matrix.Dimensions_Not_Equal -> Error.throw error diff --git a/distribution/std-lib/Standard/src/Main.enso b/distribution/std-lib/Standard/src/Main.enso index e69de29bb2..f2099ac3bc 100644 --- a/distribution/std-lib/Standard/src/Main.enso +++ b/distribution/std-lib/Standard/src/Main.enso @@ -0,0 +1,3 @@ +from Standard.Base import all + +from Standard.Base export all diff --git a/distribution/std-lib/Standard/src/Table.enso b/distribution/std-lib/Standard/src/Table.enso index c3028c4edc..b0bd0e14da 100644 --- a/distribution/std-lib/Standard/src/Table.enso +++ b/distribution/std-lib/Standard/src/Table.enso @@ -16,23 +16,23 @@ from Standard.Table.Data.Order_Rule export Order_Rule ## Converts a JSON array into a dataframe, by looking up the requested keys from each item. + Arguments: + - fields: a vector of texts representing the names of fields to look up. + The function assumes the elements have one of the following structures: - a JSON object containing the requested keys. In case an item is not an object, or the request key does not exist, the relevant values of the table will be set to `Nothing`. - a GeoJSON object of type Feature. The format is described in rfc7946. - ? Implementation Node - GeoJson support is partial. + ? Implementation Note + The GeoJson support is only partial. - Supported geometry objects are Position and Point. Rows containing other geometry objects are not included in the resulting dataframe. - Position arrays are truncated to 3 elements: longitude, latitude and elevation. - Nested properties are not supported and not included in the resulting dataframe. - - Arguments: - - fields: a vector of texts representing the names of fields to look up. Json.Array.to_table : Vector -> Table Json.Array.to_table fields = case this of Json.Array items -> @@ -48,21 +48,21 @@ Json.Array.to_table fields = case this of ## Converts a JSON object into a dataframe, by looking up the requested keys from each item. + Arguments: + - fields: a vector of texts representing the names of fields to look up. + The function assumes the elements have one of the following structures: - a GeoJSON object of type FeatureCollection. The format is described in rfc7946. - ? Implementation Node - GeoJson support is partial. + ? Implementation Note + The GeoJson support is only partial. - Supported geometry objects are Position and Point. Rows containing other geometry objects are not included in the resulting dataframe. - Position arrays are truncated to 3 elements: longitude, latitude and elevation. - Nested properties are not supported and not included in the resulting dataframe. - - Arguments: - - fields: a vector of texts representing the names of fields to look up. Json.Object.to_table : Vector -> Table ! Nothing Json.Object.to_table fields=Nothing = if this.get_type != Geo_Json.Feature_Collection.to_text then Error.throw Nothing else diff --git a/distribution/std-lib/Standard/src/Table/Data/Column.enso b/distribution/std-lib/Standard/src/Table/Data/Column.enso index 5d910db733..5ddef37381 100644 --- a/distribution/std-lib/Standard/src/Table/Data/Column.enso +++ b/distribution/std-lib/Standard/src/Table/Data/Column.enso @@ -6,14 +6,27 @@ import Standard.Table.Data.Storage polyglot java import org.enso.table.data.table.Column as Java_Column polyglot java import org.enso.table.operations.OrderBuilder +## Creates a new column given a name and a vector of elements. + + Arguments: + - name: The name of the column to create. + - items: The elements to contain in the column. +from_vector : Text -> Vector -> Column +from_vector name items = Column (Java_Column.fromItems name items.to_array) + type Column + + ## A representation of a column in a Table. + + Arguments: + - java_column: The internal representation of the column. type Column java_column ## Returns a text containing an ASCII-art table displaying this data. Arguments: - - show_rows: the number of initial rows that should be displayed. - - format_terminal: whether ANSI-terminal formatting should be used + - show_rows: the number of initial rows that should be displayed. + - format_terminal: whether ANSI-terminal formatting should be used display : Integer -> Boolean -> Text display show_rows=10 format_terminal=False = java_col = this.java_column @@ -34,97 +47,158 @@ type Column ## Prints an ASCII-art table with this data to the standard output. Arguments: - - show_rows: the number of initial rows that should be displayed. + - show_rows: the number of initial rows that should be displayed. + print : Integer -> Nothing print show_rows=10 = IO.println (this.display show_rows format_terminal=True) IO.println '' - ## Element-wise equality comparison. Returns a column with results of - comparing this column's elements against `other`. - If `other` is a column, the comparison is performed pairwise between - corresponding elements of `this` and `other`. + ## Element-wise equality comparison. + + Arguments: + - other: The value to compare `this` against. If `other` is a column, the + comparison is performed pairwise between corresponding elements of + `this` and `other`. + + Returns a column with results of comparing this column's elements against + `other`. == : Column | Any -> Column == other = here.run_vectorized_binary_op this "==" (==) other - ## Element-wise non-equality comparison. Returns a column with results of - comparing this column's elements against `other`. - If `other` is a column, the comparison is performed pairwise between - corresponding elements of `this` and `other`. + ## Element-wise non-equality comparison. + + Arguments: + - other: The value to compare `this` against. If `other` is a column, the + comparison is performed pairwise between corresponding elements of + `this` and `other`. + + Returns a column with results of comparing this column's elements against + `other`. != : Column | Any -> Column != other = (this == other).not - ## Element-wise order comparison. Returns a column with results of - comparing this column's elements against `other`. - If `other` is a column, the comparison is performed pairwise between - corresponding elements of `this` and `other`. + ## Element-wise order comparison. + + Arguments: + - other: The value to compare `this` against. If `other` is a column, the + comparison is performed pairwise between corresponding elements of + `this` and `other`. + + Returns a column with results of comparing this column's elements against + `other`. >= : Column | Any -> Column >= other = here.run_vectorized_binary_op this ">=" (>=) other - ## Element-wise order comparison. Returns a column with results of - comparing this column's elements against `other`. - If `other` is a column, the comparison is performed pairwise between - corresponding elements of `this` and `other`. + ## Element-wise order comparison. + + Arguments: + - other: The value to compare `this` against. If `other` is a column, the + comparison is performed pairwise between corresponding elements of + `this` and `other`. + + Returns a column with results of comparing this column's elements against + `other`. <= : Column | Any -> Column <= other = here.run_vectorized_binary_op this "<=" (<=) other - ## Element-wise order comparison. Returns a column with results of - comparing this column's elements against `other`. - If `other` is a column, the comparison is performed pairwise between - corresponding elements of `this` and `other`. + ## Element-wise order comparison. + + Arguments: + - other: The value to compare `this` against. If `other` is a column, the + comparison is performed pairwise between corresponding elements of + `this` and `other`. + + Returns a column with results of comparing this column's elements against + `other`. > : Column | Any -> Column > other = here.run_vectorized_binary_op this ">" (>) other - ## Element-wise order comparison. Returns a column with results of - comparing this column's elements against `other`. - If `other` is a column, the comparison is performed pairwise between - corresponding elements of `this` and `other`. + ## Element-wise order comparison. + + Arguments: + - other: The value to compare `this` against. If `other` is a column, the + comparison is performed pairwise between corresponding elements of + `this` and `other`. + + Returns a column with results of comparing this column's elements against + `other`. < : Column | Any -> Column < other = here.run_vectorized_binary_op this "<" (<) other - ## Element-wise addition. Returns a column containing the result - of adding `other` to each element of `this`. - If `other` is a column, the operation is performed pairwise between - corresponding elements of `this` and `other`. + ## Element-wise addition. + + Arguments: + - other: The value to add to `this`. If `other` is a column, the addition + is performed pairwise between corresponding elements of `this` and + `other`. + + Returns a column with results of adding `other` from each element of + `this`. + : Column | Any -> Column + other = here.run_vectorized_binary_op this '+' (+) other - ## Element-wise subtraction. Returns a column containing the result - of subtracting `other` from each element of `this`. - If `other` is a column, the operation is performed pairwise between - corresponding elements of `this` and `other`. + ## Element-wise subtraction. + + Arguments: + - other: The value to subtract from `this`. If `other` is a column, the + subtraction is performed pairwise between corresponding elements of + `this` and `other`. + + Returns a column with results of subtracting `other` from each element of + `this`. - : Column | Any -> Column - other = here.run_vectorized_binary_op this '-' (-) other - ## Element-wise multiplication. Returns a column containing the result - of multiplying `other` by each element of `this`. - If `other` is a column, the operation is performed pairwise between - corresponding elements of `this` and `other`. + ## Element-wise multiplication. + + Arguments: + - other: The value to multiply `this` by. If `other` is a column, the + multiplication is performed pairwise between corresponding elements of + `this` and `other`. + + Returns a column containing the result of multiplying each element of + `this` by `other`. * : Column | Any -> Column * other = here.run_vectorized_binary_op this '*' (*) other - ## Element-wise division. Returns a column containing the result - of dividing each element of `this` by `other`. - If `other` is a column, the operation is performed pairwise between - corresponding elements of `this` and `other`. + ## Element-wise division. + + Arguments: + - other: The value to divide `this` by. If `other` is a column, the + division is performed pairwise between corresponding elements of `this` + and `other`. + + Returns a column containing the result of dividing each element of `this` + by `other`. / : Column | Any -> Column / other = here.run_vectorized_binary_op this '/' (/) other - ## Element-wise boolean conjunction. Returns a column containing the result - of performing the boolean `and` on `other` and each element of `this`. - If `other` is a column, the operation is performed pairwise between - corresponding elements of `this` and `other`. + ## Element-wise boolean conjunction. + + Arguments: + - other: The value to compute the conjunction of `this` with. If `other` + is a column, the conjunction is performed pairwise between + corresponding elements of `this` and `other`. + + Returns a column containing the result of performing boolean `and` on + each element of `this` and `other`. && : Column | Any -> Column && other = here.run_vectorized_binary_op this "&&" (&&) other - ## Element-wise boolean disjunction. Returns a column containing the result - of performing the boolean `or` on `other` and each element of `this`. - If `other` is a column, the operation is performed pairwise between - corresponding elements of `this` and `other`. + ## Element-wise boolean disjunction. + + Arguments: + - other: The value to compute the disjunction of `this` with. If `other` + is a column, the disjunction is performed pairwise between + corresponding elements of `this` and `other`. + + Returns a column containing the result of performing the boolean `or` on + each element of `this` and `other`. || : Column | Any -> Column || other = here.run_vectorized_binary_op this "||" (||) other @@ -146,6 +220,9 @@ type Column ## Returns a new column where missing values have been replaced with the provided default. + + Arguments: + - default: The value to replace missing values with. fill_missing : Any -> Column fill_missing default = storage = this.java_column.getStorage @@ -161,28 +238,40 @@ type Column this.where this.is_missing.not ## Checks for each element of the column if it starts with `other`. - If `other` is a column, the operation is performed pairwise between - corresponding elements of `this` and `other`. + + Arguments: + - other: The value to compare `this` with. If `other` is a column, the + operation is performed pairwise between corresponding elements of + `this` and `other`. starts_with : Column | Text -> Column starts_with other = here.run_vectorized_binary_op this "starts_with" (a -> b -> a.starts_with b) other ## Checks for each element of the column if it ends with `other`. - If `other` is a column, the operation is performed pairwise between - corresponding elements of `this` and `other`. + + Arguments: + - other: The value to compare `this` with. If `other` is a column, the + operation is performed pairwise between corresponding elements of + `this` and `other`. ends_with : Column | Text -> Column ends_with other = here.run_vectorized_binary_op this "ends_with" (a -> b -> a.ends_with b) other ## Checks for each element of the column if it contains `other`. - If `other` is a column, the operation is performed pairwise between - corresponding elements of `this` and `other`. + + Arguments: + - other: The value to compare `this` with. If `other` is a column, the + operation is performed pairwise between corresponding elements of + `this` and `other`. contains : Column | Text -> Column contains other = here.run_vectorized_binary_op this "contains" (a -> b -> a.contains b) other ## Applies `function` to each item in this column and returns the column of results. + + Arguments: + - function: The function to apply to each element of `this` column. map : (Any -> Any) -> Column map function = storage = this.java_column.getStorage @@ -193,6 +282,11 @@ type Column ## Applies `function` to consecutive pairs of elements of `this` and `that` and returns a column of results. + + Arguments: + - that: The column to zip with `this`. + - function: A binary function that is applied to corresponding pairs of + elements of `this` and `that` to produce a value. zip : Column -> (Any -> Any -> Any) -> Column zip that function = s1 = this.java_column.getStorage @@ -203,6 +297,10 @@ type Column ## Returns a new column, containing the same elements as `this`, but with the given name. + + Arguments: + - name: The new name for the column. + rename : Text -> Column rename name = Column (this.java_column.rename name) ## Returns the name of this column. @@ -222,6 +320,7 @@ type Column count = this.length - this.count_missing ## Returns the index of this column, as a column (indexed by itself). + Throws `No_Index_Set_Error` if there is no index set. index : Column ! Table.No_Index_Set_Error index = case this.java_column.getIndex.toColumn of @@ -230,11 +329,11 @@ type Column ## Returns the value contained in this column at the given index. + Arguments: + - index: The index in the column from which to get the value. + If the value is an NA then this method returns nothing. If the index is not an index in the column it returns an `Index_Out_Of_Bounds_Error`. - - Arguments: - - `index`: The index in the column from which to get the value at : Integer -> (Any | Nothing) ! Index_Out_Of_Bounds_Error at index = valid_index = (index >= 0) && (index < this.length) @@ -245,6 +344,11 @@ type Column ## Selects only the rows of this column that correspond to `True` values in `indexes`. + + Arguments: + - indexes: A column containing boolean values that is used to mask + `this`. + This is useful for filtering the rows by given predicate. > Example @@ -288,21 +392,21 @@ type Column ## Efficiently joins two tables based on either the index or the specified key column. + Arguments: + - other: the table being the right operand of this join operation. + - on: the column of `this` that should be used as the join key. If this + argument is not provided, the index of `this` will be used. + - drop_unmatched: whether the rows of `this` without corresponding + matches in `other` should be dropped from the result. + - left_suffix: a suffix that should be added to the columns of `this` + when there's a name conflict with a column of `other`. + - right_suffix: a suffix that should be added to the columns of `other` + when there's a name conflict with a column of `this`. + The resulting table contains rows of `this` extended with rows of `other` with matching indexes. If the index values in `other` are not unique, the corresponding rows of `this` will be duplicated in the result. - - Arguments: - - other: the table being the right operand of this join operation. - - on: the column of `this` that should be used as the join key. If - this argument is not provided, the index of `this` will be used. - - drop_unmatched: whether the rows of `this` without corresponding - matches in `other` should be dropped from the result. - - left_suffix: a suffix that should be added to the columns of `this` - when there's a name conflict with a column of `other`. - - right_suffix: a suffix that should be added to the columns of `other` - when there's a name conflict with a column of `this`. join : Table.Table | Column -> Text | Nothing -> Boolean -> Text -> Text -> Table join other on=Nothing drop_unmatched=False left_suffix='_left' right_suffix='_right' = this.to_table.join other on drop_unmatched left_suffix right_suffix @@ -350,14 +454,14 @@ type Column Sorts the column according to the specified rules. Arguments: - - order: specifies the default sort order for this operation. - - missing_last: specifies the default placement of missing values when - compared to non-missing ones. Note thet this argument is independent - from `order`, i.e. missing values will always be sorted according to - this rule, ignoring the ascending / descending setting. - - comparator: function taking two items in this column and returning - an ordering. If specified, it is used instead of the natural - (`.compare_to`) ordering. + - order: specifies the default sort order for this operation. + - missing_last: specifies the default placement of missing values when + compared to non-missing ones. Note thet this argument is independent + from `order`, i.e. missing values will always be sorted according to + this rule, ignoring the ascending / descending setting. + - comparator: function taking two items in this column and returning + an ordering. If specified, it is used instead of the natural + (`.compare_to`) ordering. > Example Sorting `column` in ascending order. @@ -368,7 +472,8 @@ type Column top of the resulting column. column.sort order=Sort_Order.Descending missing_last=False - > Sorting `column` in ascending order, using a custom comparator + > Example + Sorting `column` in ascending order, using a custom comparator function. manhattan_comparator a b = (a.x.abs + a.y.abs) . compare_to (b.x.abs + b.y.abs) column.sort comparator=manhattan_comparator @@ -449,10 +554,6 @@ type Column mask = OrderBuilder.buildReversedMask this.length Column <| this.java_column.applyMask mask -## Creates a new column given a name and a vector of elements. -from_vector : Text -> Vector -> Column -from_vector name items = Column (Java_Column.fromItems name items.to_array) - ## Wraps a column grouped by its index. Allows performing aggregation operations on the contained values. type Aggregate_Column @@ -462,12 +563,12 @@ type Aggregate_Column with the provided `function`. Arguments: - - function: the function used for value aggregation. Values belonging - to each group are passed to this function in a vector. - - skip_missing: controls whether missing values should be included - in groups. - - name_suffix: a suffix that will be appended to the original column - name to generate the resulting column name. + - function: the function used for value aggregation. Values belonging to + each group are passed to this function in a vector. + - skip_missing: controls whether missing values should be included in + groups. + - name_suffix: a suffix that will be appended to the original column name + to generate the resulting column name. reduce : (Vector.Vector -> Any) -> Boolean -> Text -> Column reduce function skip_missing=True name_suffix="_result" = f arr = function (Vector.Vector arr) @@ -477,8 +578,8 @@ type Aggregate_Column ## Sums the values in each group. Arguments: - - name_suffix: a suffix that will be appended to the original column - name to generate the resulting column name. + - name_suffix: a suffix that will be appended to the original column name + to generate the resulting column name. sum : Text -> Column sum name_suffix='_sum' = r = this.java_column.aggregate 'sum' name_suffix (x-> Vector.Vector x . reduce (+)) True @@ -487,8 +588,8 @@ type Aggregate_Column ## Computes the maximum element of each group. Arguments: - - name_suffix: a suffix that will be appended to the original column - name to generate the resulting column name. + - name_suffix: a suffix that will be appended to the original column name + to generate the resulting column name. max : Text -> Column max name_suffix='_max' = r = this.java_column.aggregate 'max' name_suffix (x-> Vector.Vector x . reduce Math.max) True @@ -497,8 +598,8 @@ type Aggregate_Column ## Computes the minimum element of each group. Arguments: - - name_suffix: a suffix that will be appended to the original column - name to generate the resulting column name. + - name_suffix: a suffix that will be appended to the original column name + to generate the resulting column name. min : Text -> Column min name_suffix='_min' = r = this.java_column.aggregate 'min' name_suffix (x-> Vector.Vector x . reduce Math.min) True @@ -507,8 +608,8 @@ type Aggregate_Column ## Computes the number of non-missing elements in each group. Arguments: - - name_suffix: a suffix that will be appended to the original column - name to generate the resulting column name. + - name_suffix: a suffix that will be appended to the original column name + to generate the resulting column name. count : Text -> Column count name_suffix='_count' = r = this.java_column.aggregate 'count' name_suffix (x-> x.length) True @@ -517,8 +618,8 @@ type Aggregate_Column ## Computes the mean of non-missing elements in each group. Arguments: - - name_suffix: a suffix that will be appended to the original column - name to generate the resulting column name. + - name_suffix: a suffix that will be appended to the original column name + to generate the resulting column name. mean : Text -> Column mean name_suffix='_mean' = vec_mean v = if v.length == 0 then Nothing else @@ -530,14 +631,23 @@ type Aggregate_Column such vectors. Arguments: - - name_suffix: a suffix that will be appended to the original column - name to generate the resulting column name. + - name_suffix: a suffix that will be appended to the original column name + to generate the resulting column name. values : Text -> Column values name_suffix='_values' = r = this.java_column.aggregate Nothing name_suffix Vector.Vector False Column r ## PRIVATE + + Executes a vectorized binary operation over the provided column. + + Arguments: + - column: The column to execute the operation over. + - name: The name of the vectorized operation. + - fallback_fn: A function used if the vectorized operation isn't available. + - operand: The operand to apply to the function after `column`. +run_vectorized_binary_op : Column -> Text -> (Any -> Any) -> Any -> Column run_vectorized_binary_op column name fallback_fn operand = case operand of Column col2 -> s1 = column.java_column.getStorage @@ -552,46 +662,75 @@ run_vectorized_binary_op column name fallback_fn operand = case operand of Column (Java_Column.new "Result" ix rs) ## PRIVATE + + Executes a vectorized unary operation over the provided column. + + Arguments: + - column: The column to execute the operation over. + - name: The name of the vectorized operation. + - fallback_fn: A function used if the vectorized operation isn't available. +run_vectorized_unary_op : Column -> Text -> (Any -> Any) -> Column run_vectorized_unary_op column name fallback_fn = s = column.java_column.getStorage ix = column.java_column.getIndex rs = s.map name fallback_fn Column (Java_Column.new "Result" ix rs) - ## PRIVATE Keep this in sync with `org.enso.table.data.Storage.Type.LONG` +storage_type_long : Integer storage_type_long = 1 ## PRIVATE Keep this in sync with `org.enso.table.data.Storage.Type.DOUBLE` +storage_type_double : Integer storage_type_double = 2 ## PRIVATE Keep this in sync with `org.enso.table.data.Storage.Type.STRING` +storage_type_string : Integer storage_type_string = 3 ## PRIVATE Keep this in sync with `org.enso.table.data.Storage.Type.BOOL` +storage_type_bool : Integer storage_type_bool = 4 ## PRIVATE + + A helper function for converting a column storage to JSON. + + Arguments: + - storage: The storage to convert to JSON. + - factory: The factory function for converting the storage. +storage_to_json : Storage -> (Any -> Json) -> Json storage_to_json storage factory = Vector.new storage.size ix-> if storage.isNa ix then Json.Null else factory (storage.getItem ix) ## PRIVATE + + Gets a textual representation of the item at position `ix` in `column`. + + Arguments: + - column: The column to get the item from. + - ix: The index in the column from which to get the item. +get_item_string : Column -> Integer -> Text get_item_string column ix = tp = column.getType if tp == Storage_Type_String then column.getItem ix else column.getItem ix . to_text ## A type representing an error for an out-of-bounds index in a column. + + Arguments: + - index: The index of the element requested. + - length: The length of the column in which `index` was out of bounds. type Index_Out_Of_Bounds_Error index length ## Pretty-prints the index out of bounds error. diff --git a/distribution/std-lib/Standard/src/Table/Data/Order_Rule.enso b/distribution/std-lib/Standard/src/Table/Data/Order_Rule.enso index 70bde8ef76..0c0168ed88 100644 --- a/distribution/std-lib/Standard/src/Table/Data/Order_Rule.enso +++ b/distribution/std-lib/Standard/src/Table/Data/Order_Rule.enso @@ -1,29 +1,30 @@ from Standard.Base import all type Order_Rule + ## UNSTABLE A rule used for sorting table-like structures. Arguments: - - column: a value representing the data dimension by which this rule is - sorting. This type does not specify the underlying representation of - a column, assuming that the sorting engine defines its own column - representation. - - comparator: a function taking two elements of the data being sorted - on and returning an `Ordering`. The function may be `Nothing`, in - which case a natural ordering will be used. Note that certain table - backends (such us database connectors) may not support this field - being set to a non-`Nothing` value. - - order: specifies whether the table should be sorted in an ascending - or descending order. The default value of `Nothing` delegates the - decision to the sorting function. Can be set to - `Sort_Order.Ascending` or `Sort_Order.Descending` from the `Base` - library, to specify the ordering. - - missing_last: whether the missing values should be placed at the - beginning or end of the sorted table. Note that this argument is - independent from `order`, i.e. missing values will always be sorted - according to this rule, ignoring the ascending / descending setting. - The default value of `Nothing` delegates the decision to the sorting - function. + - column: a value representing the data dimension by which this rule is + sorting. This type does not specify the underlying representation of a + column, assuming that the sorting engine defines its own column + representation. + - comparator: a function taking two elements of the data being sorted on + and returning an `Ordering`. The function may be `Nothing`, in which + case a natural ordering will be used. Note that certain table backends + (such us database connectors) may not support this field being set to a + non-`Nothing` value. + - order: specifies whether the table should be sorted in an ascending or + descending order. The default value of `Nothing` delegates the decision + to the sorting function. Can be set to `Sort_Order.Ascending` or + `Sort_Order.Descending` from the `Base` library, to specify the + ordering. + - missing_last: whether the missing values should be placed at the + beginning or end of the sorted table. Note that this argument is + independent from `order`, i.e. missing values will always be sorted + according to this rule, ignoring the ascending / descending setting. + The default value of `Nothing` delegates the decision to the sorting + function. type Order_Rule column comparator=Nothing order=Nothing missing_last=Nothing diff --git a/distribution/std-lib/Standard/src/Table/Data/Storage.enso b/distribution/std-lib/Standard/src/Table/Data/Storage.enso index 0462b0d0d0..a386700738 100644 --- a/distribution/std-lib/Standard/src/Table/Data/Storage.enso +++ b/distribution/std-lib/Standard/src/Table/Data/Storage.enso @@ -1,7 +1,17 @@ ## Represents different types of underlying storage for Columns. type Type + + ## A column storing text data. type Text + + ## A column storing integer data. type Integer + + ## A column storing decimal data. type Decimal + + ## A column storing boolean data. type Boolean + + ## A column storing arbitrary data. type Any diff --git a/distribution/std-lib/Standard/src/Table/Data/Table.enso b/distribution/std-lib/Standard/src/Table/Data/Table.enso index de7206bcd9..cc563382d6 100644 --- a/distribution/std-lib/Standard/src/Table/Data/Table.enso +++ b/distribution/std-lib/Standard/src/Table/Data/Table.enso @@ -10,20 +10,76 @@ polyglot java import org.enso.table.data.table.Table as Java_Table polyglot java import org.enso.table.operations.OrderBuilder ## An error returned when a non-existent column is being looked up. + + Arguments: + - column_name: The name of the column that doesn't exist. type No_Such_Column_Error column_name ## An error returned when getting an index but no index is set for that table. type No_Index_Set_Error +## Creates a new table from a vector of column names and a vector of vectors + specifying row contents. + + Arguments: + - header: A list of texts specifying the column names + - rows: A vector of vectors, specifying the contents of each table row. The + length of each element of `rows` must be equal in length to `header`. + + > Example + The code below creates a table with 3 columns, named `foo`, `bar`, and + `baz`, containing `[1, 2, 3]`, `[True, False, True]`, and `['a', 'b', 'c']`, + respectively. + header = [ 'foo' , 'bar' , 'baz' ] + row_1 = [ 1 , True , 'a' ] + row_2 = [ 2 , False , 'b' ] + row_3 = [ 3 , True , 'c' ] + Table.from_rows header [row_1, row_2, row_3] +from_rows : Vector.Vector -> Vector.Vector -> Table +from_rows header rows = + columns = header.map_with_index i-> name-> [name, rows.map (_.at i)] + here.new columns + +## Creates a new table from a vector of `[name, items]` pairs. + + Arguments: + - columns: The `[name, items]` pairs to construct a new table from. + + > Example + Create a new table with the given in two columns: + Table.new [["foo", [1, 2, 3]], ["bar", [True, False, True]]] +new : Vector -> Table +new columns = + cols = columns.map c-> + Column.from_vector (c.at 0) (c.at 1) . java_column + here.from_columns cols + +## Joins a vector of tables (or columns) into a single table, using each table's + index as the join key. + + Arguments: + - tables: A vector of tables to join into a single table. + + Particularly useful for joining multiple columns derived from one original + table into a new table. +join : Vector -> Table +join tables = + tables.reduce .join + ## Represents a column-oriented table data structure. type Table + + ## A table. + + Arguments: + - java_table: The internal java representation of the table. type Table java_table ## Returns a text containing an ASCII-art table displaying this data. Arguments: - - show_rows: the number of initial rows that should be displayed. - - format_terminal: whether ANSI-terminal formatting should be used + - show_rows: the number of initial rows that should be displayed. + - format_terminal: whether ANSI-terminal formatting should be used display : Integer -> Boolean -> Text display show_rows=10 format_terminal=False = cols = Vector.Vector this.java_table.getColumns @@ -44,7 +100,7 @@ type Table ## Prints an ASCII-art table with this data to the standard output. Arguments: - - show_rows: the number of initial rows that should be displayed. + - show_rows: the number of initial rows that should be displayed. print show_rows=10 = IO.println (this.display show_rows format_terminal=True) IO.println '' @@ -61,6 +117,7 @@ type Table ADVANCED Returns a Text used to display this table in the IDE by default. + Returns a JSON object containing useful metadata and previews of column values. to_default_visualization_data : Text @@ -74,6 +131,9 @@ type Table Json.from_pairs [row_count, ['columns', cols]] . to_text ## Returns the column with the given name. + + Arguments: + - name: The name of the column being looked up. at : Text -> Column ! No_Such_Column_Error at name = case this.java_table.getColumnByName name of Nothing -> Error.throw (No_Such_Column_Error name) @@ -82,13 +142,13 @@ type Table ## Selects only the rows of this table that correspond to `True` values in `indexes`. - This is useful for filtering the rows by given predicate. - Arguments: - indexes: The column to mask the table by. This column should contain boolean values (`True` or `False`) that determine whether or not the corresponding row is kept. + This is useful for filtering the rows by given predicate. + > Example Select only the rows of `my_table` where the `"Status"` column has the value `"Valid"` @@ -97,8 +157,14 @@ type Table where indexes = Table (this.java_table.mask indexes.java_column) - ## Sets the column value at the given name. If a column with the given name - already exists, it will be replaced. Otherwise a new column is added. + ## Sets the column value at the given name. + + Arguments: + - name: The name of the column to set the value of. + - column: The new value for the column called `name`. + + If a column with the given name already exists, it will be replaced. + Otherwise a new column is added. set : Text -> Column.Column | Vector.Vector -> Table set name column = case column of Vector.Vector _ -> @@ -112,6 +178,9 @@ type Table Vector.Vector this.java_table.getColumns . map Column.Column ## Sets the index of this table, using the column with the provided name. + + Arguments: + - index: The name of the column to use as the index in this table. set_index : Text -> Table set_index index = Table (this.java_table.indexFromColumn index) @@ -132,21 +201,21 @@ type Table ## Efficiently joins two tables based on either the index or the specified key column. + Arguments: + - other: The table being the right operand of this join operation. + - on: The column of `this` that should be used as the join key. If this + argument is not provided, the index of `this` will be used. + - drop_unmatched: Whether the rows of `this` without corresponding + matches in `other` should be dropped from the result. + - left_suffix: A suffix that should be added to the columns of `this` + when there's a name conflict with a column of `other`. + - right_suffix: A suffix that should be added to the columns of `other` + when there's a name conflict with a column of `this`. + The resulting table contains rows of `this` extended with rows of `other` with matching indexes. If the index values in `other` are not unique, the corresponding rows of `this` will be duplicated in the result. - - Arguments: - - other: the table being the right operand of this join operation. - - on: the column of `this` that should be used as the join key. If - this argument is not provided, the index of `this` will be used. - - drop_unmatched: whether the rows of `this` without corresponding - matches in `other` should be dropped from the result. - - left_suffix: a suffix that should be added to the columns of `this` - when there's a name conflict with a column of `other`. - - right_suffix: a suffix that should be added to the columns of `other` - when there's a name conflict with a column of `this`. join : Table | Column.Column -> Text | Nothing -> Boolean -> Text -> Text -> Table join other on=Nothing drop_unmatched=False left_suffix='_left' right_suffix='_right' = case other of @@ -220,27 +289,27 @@ type Table Sorts the table according to the specified rules. Arguments: - - by: specifies the columns used for reordering the table. This - argument may be one of: - - a text: the text is treated as a column name. - - a column: any column, that may or may not belong to this table. - Sorting by a column will result in reordering the rows of this - table in a way that would result in sorting the given column. - - an order rule: specifies both the sorting column and additional - settings, that will take precedence over the global parameters of - this sort operation. The `column` field of the rule may be a text - or a column, with the semantics described above. - - a vector of any of the above: this will result in a hierarchical - sorting, such that the first rule is applied first, the second is - used for breaking ties, etc. - - order: specifies the default sort order for this operation. All the - rules specified in the `by` argument will default to this setting, - unless specified in the rule. - - missing_last: specifies the default placement of missing values when - compared to non-missing ones. This setting may be overriden by the - particular rules of the `by` argument. Note thet this argument is - independent from `order`, i.e. missing values will always be sorted - according to this rule, ignoring the ascending / descending setting. + - by: Specifies the columns used for reordering the table. This argument + may be one of: + - a text: The text is treated as a column name. + - a column: Any column, that may or may not belong to this table. + Sorting by a column will result in reordering the rows of this + table in a way that would result in sorting the given column. + - an order rule: Specifies both the sorting column and additional + settings, that will take precedence over the global parameters of + this sort operation. The `column` field of the rule may be a text + or a column, with the semantics described above. + - a vector of any of the above: This will result in a hierarchical + sorting, such that the first rule is applied first, the second is + used for breaking ties, etc. + - order: Specifies the default sort order for this operation. All the + rules specified in the `by` argument will default to this setting, + unless specified in the rule. + - missing_last: Specifies the default placement of missing values when + compared to non-missing ones. This setting may be overriden by the + particular rules of the `by` argument. Note thet this argument is + independent from `order`, i.e. missing values will always be sorted + according to this rule, ignoring the ascending / descending setting. > Example Sorting `table` in ascending order by the value in column `'Quantity'` @@ -282,6 +351,14 @@ type Table Table new_table ## PRIVATE + + Transforms order rules from Enso into Java. + + Arguments: + - rules: The rule(s) to convert. + - order: The sorting order. + - missing_last: Whether or not missing values should be ordered last. + build_java_order_rules : (Text | Column.Column. | Order_Rule | Vector (Text | Column.Column | Order_Rule)) -> Sort_Order -> Boolean -> Vector build_java_order_rules rules order missing_last = case rules of Text -> [this.build_java_order_rule rules order missing_last] Column.Column _ -> [this.build_java_order_rule rules order missing_last] @@ -289,6 +366,14 @@ type Table Vector.Vector _ -> rules.map (this.build_java_order_rule _ order missing_last) ## PRIVATE + + Builds a java order rule. + + Arguments: + - rule: The rule to convert. + - order: The sort order. + - missing_last: Whether or not missing values should be ordered last. + build_java_order_rule : (Text | Column.Column | Order_Rule) -> Sort_Order -> Boolean -> OrderRule build_java_order_rule rule order missing_last = order_bool = case order of Sort_Order.Ascending -> True @@ -317,9 +402,14 @@ type Table ## UNSTABLE - Concatenates `other` to `this`. Any column that is present in one table, - but missing in another, will be `Nothing`-padded in the positions - corresponding to the missing column. + Concatenates `other` to `this`. + + Arguments: + - other: The table to concatenate to `this`. + + Any column that is present in one table, but missing in another, will be + `Nothing`-padded in the positions corresponding to the missing column. + concat : Table -> Table concat other = Table (this.java_table.concat other.java_table) @@ -390,10 +480,23 @@ type Table Table <| this.java_table.applyMask mask ## PRIVATE + + Wraps the Enso comparator function so it's usable in Java. + + Arguments: + - cmp: The Enso comparator function. + - x: The left operand to the compartor. + - y: The right operand to the comparator. +comparator_to_java : (Any -> Any -> Ordering) -> Any -> Any -> Integer comparator_to_java cmp x y = cmp x y . to_sign ## Represents a table with grouped rows. type Aggregate_Table + + ## A table type with grouped rows. + + Arguments: + - java_table: The internal representation of the table. type Aggregate_Table java_table ## Returns a vector of aggregate columns in this table. @@ -411,69 +514,44 @@ type Aggregate_Table count = Column.Column this.java_table.count ## Returns an aggregate column with the given name, contained in this table. - at : Text -> Column | Nothing + + Arguments: + - name: The name of the aggregate column to get. + at : Text -> Column ! Nothing at name = case this.java_table.getColumnByName name of - Nothing -> Nothing + Nothing -> Error.throw Nothing c -> Column.Aggregate_Column c ## Prints an ASCII-art table with this data to the standard output. Arguments: - - show_rows: the number of initial rows that should be displayed. + - show_rows: the number of initial rows that should be displayed. print : Integer -> Nothing print show_rows=10 = this.values.print show_rows ## PRIVATE from_columns cols = Table (Java_Table.new cols.to_array) -## Creates a new table from a vector of column names and a vector of vectors - specifying row contents. - - Arguments: - - header: a list of texts specifying the column names - - rows: a vector of vectors, specifying the contents of each table row. - the length of each element of `rows` must be equal in length to `header`. - - > Example - The code below creates a table with 3 columns, named `foo`, `bar`, and - `baz`, containing `[1, 2, 3]`, `[True, False, True]`, and `['a', 'b', 'c']`, - respectively. - header = [ 'foo' , 'bar' , 'baz' ] - row_1 = [ 1 , True , 'a' ] - row_2 = [ 2 , False , 'b' ] - row_3 = [ 3 , True , 'c' ] - Table.from_rows header [row_1, row_2, row_3] -from_rows : Vector.Vector -> Vector.Vector -> Table -from_rows header rows = - columns = header.map_with_index i-> name-> [name, rows.map (_.at i)] - here.new columns - -## Creates a new table from a vector of `[name, items]` pairs. - - > Example - Create a new table with the given in two columns: - Table.new [["foo", [1, 2, 3]], ["bar", [True, False, True]]] -new columns = - cols = columns.map c-> - Column.from_vector (c.at 0) (c.at 1) . java_column - here.from_columns cols - -## Joins a vector of tables (or columns) into a single table, using each table's - index as the join key. Particularly useful for joining multiple columns - derived from one original table into a new table. -join : Vector -> Table -join tables = - tables.reduce .join - ## PRIVATE Ensures that the `txt` has at least `len` characters by appending spaces at the end. + + Arguments: + - txt: The text to pad. + - len: The minimum length of the text. +pad : Text -> Integer -> Text pad txt len = true_len = txt.characters.length txt + (" ".repeat (len - true_len)) ## PRIVATE + + Adds ANSI bold escape sequences to text if the feature is enabled. + + Arguments: + - txt: The text to possibly bold. +ansi_bold_enabled : Text -> Text ansi_bold enabled txt = case Platform.os of ## Output formatting for Windows is not currently supported. @@ -506,3 +584,4 @@ print_table header rows indices_count format_term = y = with_bold_ix . join ' | ' " " + y ([" " + header_line, divider] + row_lines).join '\n' + diff --git a/distribution/std-lib/Standard/src/Table/Internal/Java_Exports.enso b/distribution/std-lib/Standard/src/Table/Internal/Java_Exports.enso index c46b40cc98..af7173fede 100644 --- a/distribution/std-lib/Standard/src/Table/Internal/Java_Exports.enso +++ b/distribution/std-lib/Standard/src/Table/Internal/Java_Exports.enso @@ -8,21 +8,27 @@ polyglot java import org.enso.table.data.column.builder.object.NumericBuilder polyglot java import org.enso.table.data.column.builder.object.BoolBuilder ## PRIVATE +make_bool_builder : BoolBuilder make_bool_builder = BoolBuilder.new ## PRIVATE +make_double_builder : NumericBuilder make_double_builder initial_size = NumericBuilder.createDoubleBuilder initial_size ## PRIVATE +make_long_builder : NumericBuilder make_long_builder initial_size = NumericBuilder.createLongBuilder initial_size ## PRIVATE +make_inferred_builder : NumericBuilder make_inferred_builder initial_size = InferredBuilder.new initial_size ## PRIVATE +make_column : Text -> Storage -> Column make_column name storage = Column.new name storage ## PRIVATE +make_table_without_columns : Integer -> Table make_table_without_columns row_count = index = DefaultIndex.new row_count Table.new [].to_array index diff --git a/distribution/std-lib/Standard/src/Table/Io/Csv.enso b/distribution/std-lib/Standard/src/Table/Io/Csv.enso index 865a21caf9..b5dab8fc05 100644 --- a/distribution/std-lib/Standard/src/Table/Io/Csv.enso +++ b/distribution/std-lib/Standard/src/Table/Io/Csv.enso @@ -7,13 +7,13 @@ polyglot java import org.enso.table.format.csv.Parser ## Reads the contents of `this` and parses them as a CSV dataframe. Arguments - - has_header: Specifies whether the first line of the file should be - interpreted as a header, containing storage names. If set to `False`, - storage names will be automatically generated. - - prefix: text that should be prepended to automatically generated storage - names. For example, if `prefix` is set to `X`, the columns will be named - `X0`, `X1`, etc. This argument has no effect if the storage name is - inferred from the CSV header row or set manually. + - has_header: Specifies whether the first line of the file should be + interpreted as a header, containing storage names. If set to `False`, + storage names will be automatically generated. + - prefix: text that should be prepended to automatically generated storage + names. For example, if `prefix` is set to `X`, the columns will be named + `X0`, `X1`, etc. This argument has no effect if the storage name is + inferred from the CSV header row or set manually. File.File.read_csv : Boolean -> Text -> Table File.File.read_csv has_header=True prefix='C' = parser_inst = Parser.create has_header prefix diff --git a/distribution/std-lib/Standard/src/Test.enso b/distribution/std-lib/Standard/src/Test.enso index e3c2a9241c..7f899ce83f 100644 --- a/distribution/std-lib/Standard/src/Test.enso +++ b/distribution/std-lib/Standard/src/Test.enso @@ -1,139 +1,30 @@ from Standard.Base import all -## The top-level entry point for a test suite. -type Suite specs - -## PRIVATE -type Spec name behaviors - -## PRIVATE -type Behavior name result - -## PRIVATE -Behavior.is_fail = this.result.is_fail - -## PRIVATE -Spec.is_fail = this.behaviors.any .is_fail - -## PRIVATE -Suite.is_fail = this.specs.any .is_fail - -## PRIVATE -type Finished_With_Error err stack_trace_text - -## PRIVATE -type Matched_On_Error err - -## PRIVATE -type Assertion - type Success - type Failure message - type Pending reason - - is_fail = case this of - Success -> False - Failure _ -> True - Pending _ -> False - -type Verbs - type Verbs - - start_with subject argument = - if subject.starts_with argument then Success else - here.fail (subject.to_text + " did not start with " + argument.to_text)) - - equal subject argument = - if subject == argument then Success else - msg = subject.to_text + " did not equal " + argument.to_text + "." - here.fail msg - - be subject argument = this.equal subject argument - - contain subject argument = - if subject.contains argument then Success else - msg = subject.to_text + " did not contain " + argument.to_text + "." - here.fail msg - -Any.should verb argument = verb Verbs this argument - -## Fail a test with the given message. -fail message = Panic.throw (Failure message) - -## Expect a function to fail with the provided dataflow error. -Any.should_fail_with matcher = - here.fail ("Expected an error " + matcher.to_text + " but none occurred.") - -## Expect a function to fail with the provided dataflow error. -Error.should_fail_with matcher = - caught = this.catch x->x - if caught.is_a matcher then Nothing else - here.fail ("Unexpected error " + caught.to_text + " returned.") - -## Expect a function to fail with the provided panic. -expect_panic_with ~action matcher = - res = Panic.recover action - case res of - _ -> here.fail ("Expected a " + matcher.to_text + " to be thrown, but the action succeeded.") - err = res.catch x->x - if err.is_a matcher then Nothing else - here.fail ("Unexpected error " + err.to_text + " thrown.") - -## Asserts that `this` value is equal to the expected value. -Any.should_equal that = case this == that of - True -> Success - False -> - loc = Meta.get_source_location 2 - msg = this.to_text + " did not equal " + that.to_text + " (at " + loc + ")." - Panic.throw (Failure msg) - -## Asserts that `this` value is equal to the expected value. -Error.should_equal _ = Panic.throw (Matched_On_Error this) - -## Asserts that `this` is within `epsilon` from `that`. -Decimal.should_equal that (epsilon = 0) = case this.equals that epsilon of - True -> Success - False -> - loc = Meta.get_source_location 2 - msg = this.to_text + " did not equal " + that.to_text + " (at " + loc + ")." - Panic.throw (Failure msg) - -## Asserts that the given `Boolean` is `True` -Boolean.should_be_true = case this of - True -> Success - False -> - loc = Meta.get_source_location 2 - Panic.throw (Failure "Expected False to be True (at "+loc+").") - -## Asserts that the given `Boolean` is `True`. -Error.should_be_true = Panic.throw (Matched_On_Error this) - -## Asserts that the given `Boolean` is `False` -Boolean.should_be_false = case this of - True -> - loc = Meta.get_source_location 2 - Panic.throw (Failure "Expected True to be False (at "+loc+").") - False -> Success - -## Asserts that the given `Boolean` is `False` -Error.should_be_false = Panic.throw (Matched_On_Error this) - -## PRIVATE -Spec.print_report = - IO.print_err (this.name + ":") - this.behaviors.reverse.each behavior-> - case behavior.result of - Success -> - IO.print_err (" - " + behavior.name) - Failure msg -> - IO.print_err (" - [FAILED] " + behavior.name) - IO.print_err (" Reason: " + msg) - Pending reason -> - IO.print_err (" - [PENDING] " + behavior.name) - IO.print_err (" Reason: " + reason) - ## Creates a new test group, desribing properties of the object described by `this`. + Arguments: + - specs: An action encapsulating a number of test specs or groups. + + > Example + Suite.run_main <| + Test.group "Number" <| + Test.specify "should define addition" <| + 2+3 . should_equal 5 + Test.specify "should define multiplication" <| + 2*3 . should_equal 6 +Suite.run_main : Any -> Nothing +Suite.run_main ~specs = + r = this.run specs + code = if r.is_fail then 1 else 0 + System.exit code + +## Creates a new test group, desribing properties of the object + described by `this`. + + Arguments: + - specs: An action encapsulating a number of test specs or groups. + > Example Suite.run <| Test.group "Number" <| @@ -141,6 +32,30 @@ Spec.print_report = 2+3 . should_equal 5 Test.specify "should define multiplication" <| 2*3 . should_equal 6 +Suite.run : Any -> Any +Suite.run ~specs = + r = State.run Suite (Suite Nil) <| + specs + State.get Suite + r + +## Creates a new test group, desribing properties of the object + described by `this`. + + Arguments: + - name: The name of the test group. + - behaviors: An action containing a set of specs for the group. + - pending: A reason for why the test is pending, or `Nothing` when it is not + pending. + + > Example + Suite.run <| + Test.group "Number" <| + Test.specify "should define addition" <| + 2+3 . should_equal 5 + Test.specify "should define multiplication" <| + 2*3 . should_equal 6 +group : Text -> Any -> (Text | Nothing) -> Nothing group name ~behaviors pending=Nothing = case pending of Nothing -> @@ -157,6 +72,12 @@ group name ~behaviors pending=Nothing = ## Specifies a single behavior, described by `this`. + Arguments: + - label: A description of the behavior being tested. + - behavior: An action that executes tests. + - pending: A reason for why the test is pending, or `Nothing` when it is not + pending. + > Example Suite.run <| describe "Number" <| @@ -164,6 +85,7 @@ group name ~behaviors pending=Nothing = 2+3 . should_equal 5 it "should define multiplication" <| 2*3 . should_equal 6 +specify : Text -> Any -> (Text | Nothing) -> Nothing specify label ~behavior pending=Nothing = result = case pending of Nothing -> here.run_spec behavior @@ -172,7 +94,276 @@ specify label ~behavior pending=Nothing = new_spec = Spec spec.name (Cons (Behavior label result) spec.behaviors) State.put Spec new_spec +## Asserts a property about the receiver. + + Arguments: + - verb: The property (see `Verbs`) being asserted + - argument: The argument to the verb. +Anu.should : (Verbs -> Any -> Any) -> Any -> Assertion +Any.should verb argument = verb Verbs this argument + +## Fail a test with the given message. + + Arguments: + - message: The message printed when failing the test. +fail : Text -> Assertion +fail message = Panic.throw (Failure message) + +## Expect a function to fail with the provided dataflow error. + + Arguments: + - matcher: The expected type of dataflow error contained in `this`. +Any.should_fail_with : Any -> Assertion +Any.should_fail_with matcher = + here.fail ("Expected an error " + matcher.to_text + " but none occurred.") + +## Expect a function to fail with the provided dataflow error. + + Arguments: + - matcher: The expected type of dataflow error contained in `this`. +Error.should_fail_with : Any -> Assertion +Error.should_fail_with matcher = + caught = this.catch x->x + if caught.is_a matcher then Nothing else + here.fail ("Unexpected error " + caught.to_text + " returned.") + +## Expect a function to fail with the provided panic. + + Arguments: + - action: The action to evaluate that is expected to fail with a panic. + - matcher: The expected type of the panic thrown by `action`. +expect_panic_with : Any -> Any -> Assertion +expect_panic_with ~action matcher = + res = Panic.recover action + case res of + _ -> here.fail ("Expected a " + matcher.to_text + " to be thrown, but the action succeeded.") + err = res.catch x->x + if err.is_a matcher then Nothing else + here.fail ("Unexpected error " + err.to_text + " thrown.") + +## Asserts that `this` value is equal to the expected value. + + Arguments: + - that: The value to check `this` for equality with. +Any.should_equal : Any -> Assertion +Any.should_equal that = case this == that of + True -> Success + False -> + loc = Meta.get_source_location 2 + msg = this.to_text + " did not equal " + that.to_text + " (at " + loc + ")." + here.fail msg + +## Asserts that `this` value is equal to the expected value. + + Arguments: + - _: The value to check `this` for equality with. +Error.should_equal : Any -> Assertion. +Error.should_equal _ = Panic.throw (Matched_On_Error this) + +## Asserts that `this` is within `epsilon` from `that`. + + Arguments: + - that: The value to compare `this` for equality with. + - epsilon: The epislon for comparing two decimal numbers. +Decimal.should_equal : Decimal -> Decimal -> Assertion +Decimal.should_equal that (epsilon = 0) = case this.equals that epsilon of + True -> Success + False -> + loc = Meta.get_source_location 2 + msg = this.to_text + " did not equal " + that.to_text + " (at " + loc + ")." + Panic.throw (Failure msg) + +## Asserts that the given `Boolean` is `True` +Boolean.should_be_true : Assertion +Boolean.should_be_true = case this of + True -> Success + False -> + loc = Meta.get_source_location 2 + Panic.throw (Failure "Expected False to be True (at "+loc+").") + +## Asserts that the given `Boolean` is `True`. +Error.should_be_true : Assertion +Error.should_be_true = Panic.throw (Matched_On_Error this) + +## Asserts that the given `Boolean` is `False` +Boolean.should_be_false : Assertion +Boolean.should_be_false = case this of + True -> + loc = Meta.get_source_location 2 + Panic.throw (Failure "Expected True to be False (at "+loc+").") + False -> Success + +## Asserts that the given `Boolean` is `False` +Error.should_be_false : Assertion +Error.should_be_false = Panic.throw (Matched_On_Error this) + +type Verbs + + ## Verbs that describe how tests should execute. + type Verbs + + ## Checks if the `subject` starts with `argument`. + + Arguments: + - subject: The value to check. It must have a `.starts_with` method. + - argument: The expected prefix. + start_with : Text -> Text -> Assertion + start_with subject argument = + if subject.starts_with argument then Success else + here.fail (subject.to_text + " did not start with " + argument.to_text)) + + ## Checks if the `subject` is equal to the `argument`. + + Arguments: + - subject: The value to check for equality against the provided value. + - argument: The provided value to check the `subject` for equality + against. + equal : Any -> Any -> Assertion + equal subject argument = + if subject == argument then Success else + msg = subject.to_text + " did not equal " + argument.to_text + "." + here.fail msg + + ## Checks if `subject` is `argument`. + + Arguments: + - subject: The value to check for equality against the provided value. + - argument: The provided value to check the `subject` for equality + against. + be : Any -> Any -> Assertion + be subject argument = this.equal subject argument + + ## Checks if `subject` contains `argument`. + + Arguments: + - subject: The collection type to check if `argument` is contained in it. + This type must have a `.contains` method. + - argument: The value to see if it is contained in `subject`. + contain : Any -> Any -> Assertion + contain subject argument = + if subject.contains argument then Success else + msg = subject.to_text + " did not contain " + argument.to_text + "." + here.fail msg + ## PRIVATE + + Prints a report on the tests to standard output. +Spec.print_report : Nothing +Spec.print_report = + IO.print_err (this.name + ":") + this.behaviors.reverse.each behavior-> + case behavior.result of + Success -> + IO.print_err (" - " + behavior.name) + Failure msg -> + IO.print_err (" - [FAILED] " + behavior.name) + IO.print_err (" Reason: " + msg) + Pending reason -> + IO.print_err (" - [PENDING] " + behavior.name) + IO.print_err (" Reason: " + reason) + +## PRIVATE + + The top-level entry point for a test suite. + + Arguments: + - specs: The specs contained within the test suite. +type Suite specs + +## PRIVATE + + A group of behaviors for a test. + + Arguments: + - name: The name of the spec. + - behaviors: The results of the behaviors encapsulated in that spec. +type Spec name behaviors + +## PRIVATE + + A description of a behaviors in a test. + + Arguments: + - name: The name of the behavior. + - result: The result of the behavior. +type Behavior name result + +## PRIVATE + + Checks if the behavior is a failure. +Behavior.is_fail : Boolean +Behavior.is_fail = this.result.is_fail + +## PRIVATE + + Checks if the spec group contains any failures and hence fails itself. +Spec.is_fail : Boolean +Spec.is_fail = this.behaviors.any .is_fail + +## PRIVATE + + Checks if the suite contains any failures, and hence fails itself. +Suite.is_fail : Boolean +Suite.is_fail = this.specs.any .is_fail + +## PRIVATE + + An error describing that a test finished with an unexpected error. + + Arguments: + - err: The payload of the error that triggered this error. + - stack_trace_text: A textual representation of the stack trace for the + error. +type Finished_With_Error err stack_trace_text + +## PRIVATE + + An error describing that the test runner matched on an unexpected error. + + Arguments: + - err: The payload of the error that triggered this error. +type Matched_On_Error err + +## PRIVATE +type Assertion + + ## PRIVATE + + Represents a successful behavioral test. + type Success + + ## PRIVATE + + Represents a failing behavioral test. + + Arguments: + - message: The reason why the test failed. + type Failure message + + ## PRIVATE + + Represents a pending behavioral test. + + Arguments: + - reason: Text describing why the test is pending. + type Pending reason + + ## PRIVATE + + Checks if the Assertion is a failure. + is_fail : Boolean + is_fail = case this of + Success -> False + Failure _ -> True + Pending _ -> False + +## PRIVATE + + Executes a behavior test. + + Arguments: + - behavior: The behavior to execute. +run_spec : Any -> Assertion run_spec ~behavior = recovery = Panic.recover <| result = behavior @@ -187,34 +378,3 @@ run_spec ~behavior = Failure ("An unexpected error was returned: " + err.to_display_text + '\n' + stack_trace_text) _ -> Failure ("An unexpected panic was thrown: " + ex.to_display_text + '\n' + maybeExc.get_stack_trace_text) result - -## Creates a new test group, desribing properties of the object - described by `this`. - - > Example - Suite.run <| - Test.group "Number" <| - Test.specify "should define addition" <| - 2+3 . should_equal 5 - Test.specify "should define multiplication" <| - 2*3 . should_equal 6 -Suite.run ~specs = - r = State.run Suite (Suite Nil) <| - specs - State.get Suite - r - -## Creates a new test group, desribing properties of the object - described by `this`. - - > Example - Suite.run <| - Test.group "Number" <| - Test.specify "should define addition" <| - 2+3 . should_equal 5 - Test.specify "should define multiplication" <| - 2*3 . should_equal 6 -Suite.runMain ~specs = - r = this.run specs - code = if r.is_fail then 1 else 0 - System.exit code diff --git a/distribution/std-lib/Standard/src/Test/Bench.enso b/distribution/std-lib/Standard/src/Test/Bench.enso index a817db29a9..1b61633871 100644 --- a/distribution/std-lib/Standard/src/Test/Bench.enso +++ b/distribution/std-lib/Standard/src/Test/Bench.enso @@ -1,13 +1,27 @@ from Standard.Base import all -reverse_list = list -> +## PRIVATE + + Reverses the provided list. + + Arguments: + - list: The list to reverse. +reverse_list : List Any -> List +reverse_list list = go = list -> acc -> case list of Cons h t -> @Tail_Call go t (Cons h acc) Nil -> acc res = go list Nil res -sum_list = list -> +## PRIVATE + + Sums the elements of the list. + + Arguments: + - list: The list of numbers to sum. +sum_list : List Number -> Sum +sum_list list = go = list -> acc -> case list of Cons a b -> @Tail_Call go b (acc + a) Nil -> acc @@ -15,21 +29,50 @@ sum_list = list -> res = go list 0 res -avg_list = list -> here.sum_list list / here.len_list list +## PRIVATE -len_list = list -> + Calculate the average of the elements of a numeric list. + + Arguments: + - list: The list of numbers to calculate the average of. +avg_list : List Number -> Number +avg_list list = here.sum_list list / here.len_list list + +## PRIVATE + + Calculates the length of the provided list. + + Arguments: + - list: The list to calculate the length of. +len_list : List Any -> Integer +len_list list = go = list -> acc -> case list of Cons _ b -> @Tail_Call go b (acc + 1) Nil -> acc res = go list 0 res -Number.times = act -> +## PRIVATE + + Perform an action a number of times. + + Arguments: + - act: The action to perform `this` number of times. +Number.times : List Any +Number.times act = go = results -> number -> if number == 0 then results else @Tail_Call go (Cons (act number) results) number-1 res = here.reverse_list (go Nil this) res +## Measure the amount of time it takes to execute a given computation. + + Arguments: + - act: The action to perform. + - label: A name for the measurement. + - iter_size: The number of runs per iteration. + - num_iters: The number of iterations per measurement. +measure : Any -> Text -> Integer -> Integer -> Nothing measure = ~act -> label -> iter_size -> num_iters -> single_call = _ -> x1 = System.nano_time @@ -43,3 +86,4 @@ measure = ~act -> label -> iter_size -> num_iters -> fmt = (avg / 1000000).format "%.2f" IO.println (label + "/iteration:" + act_it_num.to_text + ": " + fmt + "ms") num_iters.times iteration + diff --git a/distribution/std-lib/Standard/src/Visualization/Sql/Visualization.enso b/distribution/std-lib/Standard/src/Visualization/Sql/Visualization.enso index a1ca4f77e1..a78f4fe13d 100644 --- a/distribution/std-lib/Standard/src/Visualization/Sql/Visualization.enso +++ b/distribution/std-lib/Standard/src/Visualization/Sql/Visualization.enso @@ -6,12 +6,16 @@ import Standard.Visualization.Helpers Prepares the query for visualization. + Arguments: + - x: The query to prepare for visualisation. + For each interpolation it provides its value, its actual type name, its expected SQL type name and if it was possible to infer it, its expected Enso typename. Expected Enso types are inferred based on known SQL types and their mapping to Enso types. +prepare_visualization : Table.IR.Query -> Json prepare_visualization x = Helpers.recover_errors <| prepared = x.to_sql.prepare code = prepared.first @@ -29,8 +33,12 @@ prepare_visualization x = Helpers.recover_errors <| Return an expected Enso type for an SQL type. + Arguments: + - sql_type: The SQL type to convert to an Enso type. + Expected Enso types are only inferred for some known SQL types. For unknown types it will return `Nothing`. +find_expected_enso_type_for_sql : Sql_Type -> Text find_expected_enso_type_for_sql sql_type = if sql_type.is_definitely_integer then "Builtins.Main.Integer" else if sql_type.is_definitely_double then "Builtins.Main.Decimal" else diff --git a/distribution/std-lib/Standard/src/Visualization/Table/Visualization.enso b/distribution/std-lib/Standard/src/Visualization/Table/Visualization.enso index c43cce6a09..6f9892aead 100644 --- a/distribution/std-lib/Standard/src/Visualization/Table/Visualization.enso +++ b/distribution/std-lib/Standard/src/Visualization/Table/Visualization.enso @@ -7,11 +7,17 @@ import Standard.Database.Data.Column as Database_Column import Standard.Visualization.Helpers # TODO add an initial offset to fully support lazy visualizations + ## PRIVATE Prepares a table or column for visualization. + Arguments: + - x: The table to prepare for visualisation. + - max_rows: The maximum number of rows to display. + In case of Database backed data, it materializes a fragment of the data. +prepare_visualization : Any -> Integer -> Json prepare_visualization x max_rows = Helpers.recover_errors <| case x of Dataframe_Table.Table _ -> dataframe = x.take_start max_rows @@ -71,6 +77,7 @@ prepare_visualization x max_rows = Helpers.recover_errors <| case x of `dataframe`. - all_rows_count: the number of all rows in the underlying data, useful if only a fragment is displayed. +make_json : Table -> Vector Column -> Integer -> Json make_json dataframe indices all_rows_count = columns = dataframe.columns header = ["header", columns.map .name] diff --git a/engine/runtime/src/main/java/org/enso/interpreter/epb/node/ForeignEvalNode.java b/engine/runtime/src/main/java/org/enso/interpreter/epb/node/ForeignEvalNode.java index 4921c27590..5888978b0f 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/epb/node/ForeignEvalNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/epb/node/ForeignEvalNode.java @@ -1,6 +1,7 @@ package org.enso.interpreter.epb.node; -import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.TruffleLanguage.ContextReference; import com.oracle.truffle.api.dsl.CachedContext; import com.oracle.truffle.api.dsl.Specialization; @@ -8,20 +9,16 @@ import com.oracle.truffle.api.exception.AbstractTruffleException; import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.UnknownIdentifierException; -import com.oracle.truffle.api.interop.UnsupportedMessageException; -import com.oracle.truffle.api.nodes.IndirectCallNode; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.Source; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; import org.enso.interpreter.epb.EpbContext; import org.enso.interpreter.epb.EpbLanguage; import org.enso.interpreter.epb.EpbParser; import org.enso.interpreter.epb.runtime.GuardedTruffleContext; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - public abstract class ForeignEvalNode extends RootNode { private final EpbParser.Result code; private @Child ForeignFunctionCallNode foreign; diff --git a/engine/runtime/src/main/resources/Builtins.enso b/engine/runtime/src/main/resources/Builtins.enso index c969bf0ee9..f4ab1ceda5 100644 --- a/engine/runtime/src/main/resources/Builtins.enso +++ b/engine/runtime/src/main/resources/Builtins.enso @@ -30,7 +30,7 @@ type Boolean Arguments: - that: The boolean to compute the conjunction of this with. - ? Short Circuiting + ! Short Circuiting This method is not implemented in a short-circuiting manner. This means that even if this is False, it will also evaluate that. This is for performance. @@ -46,7 +46,7 @@ type Boolean Arguments: - that: The boolean to compute the disjunction of this with. - ? Short Circuiting + ! Short Circuiting This methid is not implemented in a short-circuiting manner. This means that even if this is True, it will also evaluate that. This is for performance. @@ -232,6 +232,10 @@ type Error get_stack_trace_text = @Builtin_Method "Error.get_stack_trace_text" ## Converts an error to a corresponding textual representation. + + > Example + Converting a thrown error to text. + Error.throw "foo" . to_text to_text : Text to_text = @Builtin_Method "Error.to_text" @@ -853,11 +857,6 @@ type Array Arguments: - index: The index to get the element from. - ? Safety - If index >= this.length, then this operation will result in an - Invalid_Array_Index_Error exception. If the element at index is - null, then this method will return null. - > Example Get the element at index 1. [1,2,3].to_array.at 1 @@ -951,8 +950,8 @@ type Ref ## The root type of the Enso numeric hierarchy. - If a Number is expected, then the program can provide both a Decimal and - an Integer in this place. + If a Number is expected, then the program can provide either a Decimal or + an Integer in its place. @Builtin_Type type Number @@ -1497,7 +1496,9 @@ type Resource @Builtin_Type type Resource - ## Acquires a resource, performs an action on it, and destroys it safely, + ## ADVANCED + + Acquires a resource, performs an action on it, and destroys it safely, even in the presence of panics. Arguments: @@ -1520,17 +1521,25 @@ type Managed_Resource @Builtin_Type type Managed_Resource - ## Registers a resource with the resource manager to be cleaned up using + ## ADVANCED + + Registers a resource with the resource manager to be cleaned up using function once it is no longer in use. Arguments: - resource: The resource to be managed automatically. - function: The action to be executed on resource to clean it up when it is no longer in use. + + > Example + Registering a managed resource. + Managed_Resource register : Any -> (Any -> Nothing) -> Managed_Resource register resource function = @Builtin_Method "Managed_Resource.register" - ## Forces finalization of a managed resource using the registered finalizer, + ## ADVANCED + + Forces finalization of a managed resource using the registered finalizer, even if the resource is still reachable. Arguments: @@ -1538,7 +1547,9 @@ type Managed_Resource finalize : Managed_Resource -> Nothing finalize resource = @Builtin_Method "Managed_Resource.finalize" - ## Executes the provided action on the resource managed by the managed + ## ADVANCED + + Executes the provided action on the resource managed by the managed resource object. Arguments: @@ -1548,7 +1559,9 @@ type Managed_Resource with : Managed_Resource -> (Any -> Any) -> Any with resource ~action = @Builtin_Method "Managed_Resource.with" - ## Takes the value held by the managed resource and unregisters the + ## ADVANCED + + Takes the value held by the managed resource and unregisters the finalization step for this resource, effectively removing it from the managed resources system. diff --git a/test/Database_Tests/src/Main.enso b/test/Database_Tests/src/Main.enso index c393e71ef7..3b1fda8a11 100644 --- a/test/Database_Tests/src/Main.enso +++ b/test/Database_Tests/src/Main.enso @@ -5,7 +5,7 @@ import Database_Tests.Codegen_Spec import Database_Tests.Sqlite_Spec import Database_Tests.Postgresql_Spec -main = Test.Suite.runMain <| +main = Test.Suite.run_main <| Codegen_Spec.spec Sqlite_Spec.spec Postgresql_Spec.spec diff --git a/test/Database_Tests/src/Sqlite_Spec.enso b/test/Database_Tests/src/Sqlite_Spec.enso index b863c594b9..b1307bf896 100644 --- a/test/Database_Tests/src/Sqlite_Spec.enso +++ b/test/Database_Tests/src/Sqlite_Spec.enso @@ -13,7 +13,7 @@ sqlite_specific_spec connection = action = connection.execute_query "SELECT A FROM undefined_table" action . should_fail_with Sql_Error - action.catch.to_text . should_equal "[SQLITE_ERROR] SQL error or missing database (no such table: undefined_table)" + action.catch.to_text . should_equal "There was an SQL error: '[SQLITE_ERROR] SQL error or missing database (no such table: undefined_table)'." Test.group "[SQLite] Metadata" <| connection.execute_update 'CREATE TABLE "Tinfo" ("strs" VARCHAR, "ints" INTEGER, "bools" BOOLEAN, "reals" REAL)' diff --git a/test/Geo_Tests/src/Main.enso b/test/Geo_Tests/src/Main.enso index 285a5316f9..f7f1da7dbf 100644 --- a/test/Geo_Tests/src/Main.enso +++ b/test/Geo_Tests/src/Main.enso @@ -4,5 +4,5 @@ import Standard.Test import Geo_Tests.Geo_Spec -main = Test.Suite.runMain <| +main = Test.Suite.run_main <| Geo_Spec.spec diff --git a/test/Image_Tests/src/Main.enso b/test/Image_Tests/src/Main.enso index 961dc2ba93..7e73d59ac8 100644 --- a/test/Image_Tests/src/Main.enso +++ b/test/Image_Tests/src/Main.enso @@ -5,7 +5,7 @@ import Image_Tests.Codecs_Spec import Image_Tests.Data.Image_Spec import Image_Tests.Data.Matrix_Spec -main = Test.Suite.runMain <| +main = Test.Suite.run_main <| Codecs_Spec.spec Matrix_Spec.spec Image_Spec.spec diff --git a/test/Table_Tests/src/Main.enso b/test/Table_Tests/src/Main.enso index c99398cc9e..2399fc2fdf 100644 --- a/test/Table_Tests/src/Main.enso +++ b/test/Table_Tests/src/Main.enso @@ -5,6 +5,6 @@ import Standard.Test import Table_Tests.Table_Spec import Table_Tests.Column_Spec -main = Test.Suite.runMain <| +main = Test.Suite.run_main <| Column_Spec.spec Table_Spec.spec diff --git a/test/Tests/src/Main.enso b/test/Tests/src/Main.enso index 6961122fd5..5d17559241 100644 --- a/test/Tests/src/Main.enso +++ b/test/Tests/src/Main.enso @@ -40,7 +40,7 @@ import Tests.Network.Uri_Spec import Tests.System.File_Spec import Tests.System.Process_Spec -main = Test.Suite.runMain <| +main = Test.Suite.run_main <| Any_Spec.spec Array_Spec.spec Case_Spec.spec diff --git a/test/Visualization_Tests/src/Main.enso b/test/Visualization_Tests/src/Main.enso index 07a439b26b..c3e92a20f4 100644 --- a/test/Visualization_Tests/src/Main.enso +++ b/test/Visualization_Tests/src/Main.enso @@ -9,7 +9,7 @@ import Visualization_Tests.Scatter_Plot_Spec import Visualization_Tests.Sql_Spec import Visualization_Tests.Table_Spec -main = Test.Suite.runMain <| +main = Test.Suite.run_main <| Geo_Map_Spec.spec Helpers_Spec.spec Histogram_Spec.spec