JSON Improvements, small Table stuff, Statistic in Enso not Java and few other minor bits. (#3964)

- Aligned `compare_to` so returns `Type_Error` if `that` is wrong type for `Text`, `Ordering` and `Duration`.
- Add `empty_object`, `empty_array`. `get_or_else`, `at`, `field_names` and `length` to `Json`.
- Fix `Json` serialisation of NaN and Infinity (to "null").
- Added `length`, `at` and `to_vector` to Pair (allowing it to be treated as a Vector).
- Added `running_fold` to the `Vector` and `Range`.
- Added `first` and `last` to the `Vector.Builder`.
- Allow `order_by` to take a single `Sort_Column` or have a mix of `Text` and `Sort_Column.Name` in a `Vector`.
- Allow `select_columns_helper` to take a `Text` value. Allows for a single field in group_by in cross_tab.
- Added `Patch` and `Custom` to HTTP_Method.
- Added running `Statistic` calculation and moved more of the logic from Java to Enso. Performance seems similar to pure Java version now.
This commit is contained in:
James Dunkerley 2022-12-14 19:40:27 +00:00 committed by GitHub
parent 3e74afca51
commit 77fe69dfd9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 579 additions and 198 deletions

View File

@ -257,6 +257,7 @@
and fixed issue with compare_to versus Nothing][3874]
- [Aligned `Text.match`/`Text.locate` API][3841]
- [Added `transpose` and `cross_tab` to the In-Memory Table.][3919]
- [Improvements to JSON, Pair, Statistics and other minor tweaks.][3964]
[debug-shortcuts]:
https://github.com/enso-org/enso/blob/develop/app/gui/docs/product/shortcuts.md#debug
@ -404,6 +405,7 @@
[3885]: https://github.com/enso-org/enso/pull/3885
[3919]: https://github.com/enso-org/enso/pull/3919
[3923]: https://github.com/enso-org/enso/pull/3923
[3964]: https://github.com/enso-org/enso/pull/3964
[3967]: https://github.com/enso-org/enso/pull/3967
#### Enso Compiler

View File

@ -49,7 +49,7 @@ type Filter_Condition
values from the source column and the provided column are checked.
Ends_With (suffix:Text)
## Does the value contain the needle (Text only)?
## Does the value contain the substring (Text only)?
? Table Operations
It accepts a Text value to check if the value contains it. In case of
@ -57,6 +57,14 @@ type Filter_Condition
values from the source column and the provided column are checked.
Contains (substring:Text)
## Is the substring not present in the value (Text only)?
? Table Operations
It accepts a Text value to check if the value contains it. In case of
Table operations, it can accept another column - then the corresponding
values from the source column and the provided column are checked.
Not_Contains (substring:Text)
## Is equal to Nothing?
Is_Nothing
@ -160,6 +168,7 @@ type Filter_Condition
Starts_With prefix -> _.starts_with prefix
Ends_With suffix -> _.ends_with suffix
Contains substring -> _.contains substring
Not_Contains substring -> v-> v.contains substring . not
Is_Nothing -> elem -> case elem of
Nothing -> True
_ -> False

View File

@ -2,7 +2,9 @@ import project.Any.Any
import project.Data.Json.Internal
import project.Data.Map.Map
import project.Data.Map.No_Value_For_Key
import project.Data.Numbers.Integer
import project.Data.Range.Extensions
import project.Data.Text.Extensions
import project.Data.Text.Text
import project.Data.Vector.Vector
import project.Error.Error
@ -113,6 +115,14 @@ type Json
into self type_descriptor =
Panic.recover Any (Internal.into_helper type_descriptor self)
## Returns an empty JSON object.
empty_object : Json
empty_object = Json.Object Map.empty
## Returns an empty JSON array.
empty_array : Json
empty_array = Json.Array []
## Returns this Json object.
This is a no-op on a JSON object, but is included to implement the
@ -150,11 +160,11 @@ type Json
## Gets the value associated with the given key in this object.
Throws `No_Such_Field` if the associated key is not defined.
Arguments:
- field: The name of the field from which to get the value.
Throws `Nothing` if the associated key is not defined.
> Example
Get the "title" field from this JSON representing a book.
@ -162,11 +172,43 @@ type Json
example_get = Examples.json_object.get "title"
get : Text -> Json ! No_Such_Field
get self field = case self of
Json.Object _ -> self.fields.get field . map_error case _ of
No_Value_For_Key.Error _ -> No_Such_Field.Error field
x -> x
_ -> Error.throw (Illegal_Argument.Error "Json.get: self must be an Object")
get self field = self.get_or_else field (Error.throw (No_Such_Field.Error field))
## Gets the value associated with the given key in this object.
Arguments:
- field: The name of the field from which to get the value.
- other: The value to return if not present. Defaults to `Json.Null`.
get_or_else : Text -> Any -> Json
get_or_else self field ~other=Json.Null = case self of
Json.Object fields -> fields.get_or_else field other
Json.Null -> other
_ -> Error.throw (Illegal_Argument.Error "Json.get_or_else: self must be an Object.")
## Gets the value associated with the given index in this object.
Arguments:
- index: The index position from which to get the value.
at : Integer -> Json ! Illegal_Argument | Out_Of_Bounds
at self index = case self of
Json.Array array -> array.at index
Json.String text -> Json.String (text.at index)
Json.Null -> Json.Null
_ -> Error.throw (Illegal_Argument.Error "Json.at: self must be a String or an Array.")
## Gets the set of field names for an object.
field_names : Vector ! Illegal_Argument
field_names self = case self of
Json.Object map -> map.keys
_ -> Error.throw (Illegal_Argument.Error "Json.field_name: self must be an Object.")
## Returns the number of items in this array or object or length of string.
length : Integer ! Illegal_Argument
length self = case self of
Json.Array array -> array.length
Json.Object map -> map.size
Json.String text -> text.length
_ -> Error.throw (Illegal_Argument.Error "Json.length: self must be a String, an Object, or an Array.")
## UNSTABLE

View File

@ -279,7 +279,7 @@ render_helper builder json = case json of
Json.String value ->
builder + (Printer.json_escape value)
Json.Number value ->
builder + value.to_text
builder + (if value.is_nan || value.is_infinite then "null" else value.to_text)
Json.Boolean value ->
val = if value then "true" else "false"
builder + val

View File

@ -348,6 +348,12 @@ type Number
_ : Decimal -> Double.isNaN self
_ -> False
## Checks if the given number is infinite.
is_infinite : Boolean
is_infinite self = case self of
_ : Decimal -> Double.isInfinite self
_ -> False
## Returns the sign of the number.
signum : Integer
signum self =

View File

@ -1,4 +1,6 @@
import project.Data.Numbers.Integer
import project.Error.Common.Type_Error
import project.Error.Error
## Types representing the ordering of values.
@ -41,7 +43,9 @@ type Ordering
Ordering.Greater -> Ordering.Greater
compare_to : Ordering -> Ordering
compare_to self other = self.to_sign.compare_to other.to_sign
compare_to self that = case that of
_ : Ordering -> self.to_sign.compare_to that.to_sign
_ -> Error.throw (Type_Error.Error Ordering that "that")
## Converts a sign-based representation of ordering to Enso's native ordering.

View File

@ -1,4 +1,8 @@
import project.Any.Any
import project.Data.Numbers.Integer
import project.Data.Vector.Vector
import project.Error.Error
import project.Error.Common.Index_Out_Of_Bounds
## A pair of elements.
type Pair
@ -30,3 +34,28 @@ type Pair
map : (Any -> Any) -> Pair
map self fun =
Pair.new (fun self.first) (fun self.second)
## UNSTABLE
Returns the length (2) of the Pair.
length : Integer
length self = 2
## UNSTABLE
Returns the pair as a Vector.
to_vector : Vector
to_vector self = [self.first, self.second]
## Gets an element from the pair at a specified index (0-based).
Arguments:
- index: The location in the pair to get the element from. The index is
also allowed be negative, then the elements are indexed from the back
of the pair, i.e. -1 will correspond to the last element.
at : Integer -> Any
at self index =
case index of
0 -> self.first
1 -> self.second
-1 -> self.second
-2 -> self.first
_ -> Error.throw (Index_Out_Of_Bounds.Error index self.length)

View File

@ -203,6 +203,25 @@ type Range
@Tail_Call go new_acc current+self.step
go init self.start
## Combines all the elements of the range, by iteratively applying the
passed function with the next element of the range. After each step the
value is stored resulting in a new Vector of the same size as self.
Arguments:
- init: The initial value for the fold.
- function: A function taking two elements and combining them.
> Example
Compute the running sum of all of the elements in a vector
[1, 2, 3].running_fold 0 (+)
running_fold : Any -> (Any -> Any -> Any) -> Vector Any
running_fold self init function =
wrapped builder value =
current = if builder.length == 0 then init else builder.last
builder.append (function current value)
built = self.fold (Vector.new_builder self.length) wrapped
built.to_vector
## Checks whether `predicate` is satisfied for all numbers in this range.

View File

@ -1,8 +1,10 @@
import project.Any.Any
import project.Data.Array.Array
import project.Data.Numbers.Decimal
import project.Data.Numbers.Integer
import project.Data.Numbers.Number
import project.Data.Ordering.Comparator
import project.Data.Ordering.Ordering
import project.Data.Range.Extensions
import project.Data.Vector.Vector
import project.Error.Error
@ -10,6 +12,7 @@ import project.Error.Illegal_Argument.Illegal_Argument
import project.Error.Incomparable_Values.Incomparable_Values
import project.Meta
import project.Nothing.Nothing
import project.Runtime.Ref.Ref
import project.Panic.Panic
from project.Data.Boolean import Boolean, True, False
@ -123,6 +126,17 @@ type Statistic
- predicted: the series to compute the r_squared with.
R_Squared (predicted:Vector)
## Gets the order needed to compute a statistic for a moment based statistic.
order : Integer | Nothing
order self = case self of
Statistic.Sum -> 1
Statistic.Mean -> 1
Statistic.Variance _ -> 2
Statistic.Standard_Deviation _ -> 2
Statistic.Skew _ -> 3
Statistic.Kurtosis -> 4
_ -> Nothing
## Compute a single statistic on a vector like object.
Arguments:
@ -139,44 +153,77 @@ type Statistic
- statistics: Set of statistics to calculate.
compute_bulk : Vector -> Vector Statistic -> Vector Any
compute_bulk data statistics=[Statistic.Count, Statistic.Sum] =
count_min_max = statistics.any s->
case s of
Statistic.Count -> True
Statistic.Minimum -> True
Statistic.Maximum -> True
_ -> False
counter = CountMinMax.new
java_stats = statistics.map to_moment_statistic
skip_java_stats = java_stats.all s->s.is_nothing
moment_order = statistics.map .order
skip_moments = moment_order.all s->s.is_nothing
moments = if skip_moments then Nothing else Moments.new (moment_order.filter (v-> v != Nothing) . fold 0 .max)
report_invalid _ =
statistics.map_with_index i->v->
if java_stats.at i . is_nothing then Nothing else
Error.throw (Illegal_Argument.Error ("Can only compute " + v.to_text + " on numerical data sets."))
handle_unsupported = Panic.catch Unsupported_Argument_Types.Error handler=report_invalid
result = data.fold moments current-> value-> compute_fold counter current value
empty_map s = if (s == Statistic.Count) || (s == Statistic.Sum) then 0 else
if (s == Statistic.Minimum) || (s == Statistic.Maximum) then Error.throw Empty_Error else
Number.nan
report_error stats =
first = 0.up_to stats.length . find i-> (moment_order.at i . is_nothing . not)
stat = stats.at first
Error.throw (Illegal_Argument.Error ("Can only compute " + stat.to_text + " on numerical data sets."))
if data.length == 0 then statistics.map empty_map else
count_min_max_values = if count_min_max then CountMinMax.new (CountMinMax.toObjectStream data.to_array) Comparator.new else Nothing
stats_array = if skip_java_stats then Nothing else
handle_unsupported <| Moments.compute data.to_array java_stats.to_array
if counter.count == 0 then statistics.map empty_value else
if skip_moments.not && result.is_nothing then report_error statistics else
statistics.map statistic-> case statistic of
Statistic.Count -> counter.count
Statistic.Minimum -> if counter.comparatorError then (Error.throw Incomparable_Values) else counter.minimum
Statistic.Maximum -> if counter.comparatorError then (Error.throw Incomparable_Values) else counter.maximum
Statistic.Covariance series -> calculate_correlation_statistics data series . covariance
Statistic.Pearson series -> calculate_correlation_statistics data series . pearsonCorrelation
Statistic.Spearman series -> calculate_spearman_rank data series
Statistic.R_Squared series -> calculate_correlation_statistics data series . rSquared
_ -> moments.compute (to_moment_statistic statistic)
statistics.map_with_index i->s->case s of
Statistic.Count -> count_min_max_values.count
Statistic.Minimum ->
if count_min_max_values.comparatorError then (Error.throw Incomparable_Values) else
count_min_max_values.minimum
Statistic.Maximum ->
if count_min_max_values.comparatorError then (Error.throw Incomparable_Values) else
count_min_max_values.maximum
Statistic.Covariance s -> calculate_correlation_statistics data s . covariance
Statistic.Pearson s -> calculate_correlation_statistics data s . pearsonCorrelation
Statistic.Spearman s -> calculate_spearman_rank data s
Statistic.R_Squared s -> calculate_correlation_statistics data s . rSquared
_ -> stats_array.at i
## Compute a running statistics on a vector like object.
Arguments:
- data: Vector like object which has a `to_array` method.
- statistics: Set of statistics to calculate.
running : Vector -> Statistic -> Vector Any
running data statistic=Statistic.Sum =
Statistic.running_bulk data [statistic] . map .first
## Compute a set running statistics on a vector like object.
Arguments:
- data: Vector like object which has a `to_array` method.
- statistics: Set of statistics to calculate.
running_bulk : Vector -> Vector Statistic -> Vector Any
running_bulk data statistics=[Statistic.Count, Statistic.Sum] =
is_unsupported s = case s of
Statistic.Covariance _ -> True
Statistic.Pearson _ -> True
Statistic.Spearman _ -> True
Statistic.R_Squared _ -> True
_ -> False
if statistics.any is_unsupported then Error.throw (Illegal_Argument.Error ("Unsupported Statistics ( " + (statistics.filter is_unsupported . to_text) ") for running calculations.")) else
counter = CountMinMax.new
moment_order = statistics.map .order
skip_moments = moment_order.all s->s.is_nothing
moments = if skip_moments then Nothing else Moments.new (moment_order.filter (v-> v != Nothing) . fold 0 .max)
ref_moment = Ref.new moments
Panic.handle_wrapped_dataflow_error <|
output = Vector.new_builder data.length
data.each value->
result = compute_fold counter ref_moment.get value
ref_moment.put result
row = Panic.throw_wrapped_if_error <| statistics.map s-> case s of
Statistic.Count -> counter.count
Statistic.Minimum -> if counter.comparatorError then (Error.throw Incomparable_Values) else counter.minimum
Statistic.Maximum -> if counter.comparatorError then (Error.throw Incomparable_Values) else counter.maximum
_ -> if result.is_nothing then Error.throw (Illegal_Argument.Error ("Can only compute " + s.to_text + " on numerical data sets.")) else result.compute (to_moment_statistic s)
output.append row
output.to_vector
## Calculate a variance-covariance matrix between the input series.
@ -279,3 +326,44 @@ Vector.compute self statistic=Statistic.Count =
Vector.compute_bulk : Vector Statistic -> Vector Any
Vector.compute_bulk self statistics=[Statistic.Count, Statistic.Sum] =
Statistic.compute_bulk self statistics
## Compute a single running statistic on the vector.
Arguments:
- statistic: Statistic to calculate.
Vector.running : Statistic -> Vector Any
Vector.running self statistic=Statistic.Count =
Statistic.running self statistic
## PRIVATE
compute_fold counter current value =
if is_valid value . not then current else
counter.increment
if counter.comparatorError.not then
if counter.minimum.is_nothing then counter.setMinimum value else
ordering = Incomparable_Values.handle_errors <| value.compare_to counter.minimum
if ordering.is_error then counter.failComparator else
if ordering == Ordering.Less then counter.setMinimum value
if counter.maximum.is_nothing then counter.setMaximum value else
ordering = Incomparable_Values.handle_errors <| value.compare_to counter.maximum
if ordering.is_error then counter.failComparator else
if ordering == Ordering.Greater then counter.setMaximum value
if current.is_nothing then Nothing else case value of
_ : Number -> current.add value
_ -> Nothing
## PRIVATE
empty_value statistic = case statistic of
Statistic.Count -> 0
Statistic.Sum -> 0
Statistic.Minimum -> Error.throw Empty_Error
Statistic.Maximum -> Error.throw Empty_Error
_ -> Number.nan
## PRIVATE
is_valid v = case v of
Nothing -> False
_ : Number -> v.is_nan.not
_ -> True

View File

@ -66,10 +66,11 @@ type Text
"a".compare_to "b"
compare_to : Text -> Ordering
compare_to self that =
if that.is_nothing then Error.throw (Type_Error.Error Text that "that") else
compare_to self that = case that of
_ : Text ->
comparison_result = Text_Utils.compare_normalized self that
Ordering.from_sign comparison_result
_ -> Error.throw (Type_Error.Error Text that "that")
## Checks whether `self` is equal to `that`, ignoring the case of the texts.

View File

@ -6,6 +6,7 @@ import project.Data.Pair.Pair
import project.Data.Time.Date_Time.Date_Time
import project.Data.Time.Period.Period
import project.Data.Vector.Vector
import project.Error.Common.Type_Error
import project.Error.Error
import project.Error.Illegal_Argument.Illegal_Argument
import project.Error.Illegal_State.Illegal_State
@ -197,9 +198,9 @@ type Duration
duration_2 = (Duration.new minutes=60) + (Duration.new minutes=5)
duration_1.compare_to duration_2
compare_to : Duration -> Ordering
compare_to self that =
ensure_duration that <|
Ordering.from_sign (self.compare_to_builtin that)
compare_to self that = case that of
_ : Duration -> Ordering.from_sign (self.compare_to_builtin that)
_ -> Error.throw (Type_Error.Error Duration that "that")
## Get the portion of the duration expressed in nanoseconds.

View File

@ -204,6 +204,26 @@ type Vector a
f = acc -> ix -> function acc ix (self.at ix)
0.up_to self.length . fold init f
## Combines all the elements of the vector, by iteratively applying the
passed function with the next element of the vector. After each step the
value is stored resulting in a new Vector of the same size as self.
Arguments:
- init: The initial value for the fold.
- function: A function taking two elements and combining them.
> Example
Compute the running sum of all of the elements in a vector
[1, 2, 3].running_fold 0 (+)
running_fold : Any -> (Any -> Any -> Any) -> Vector Any
running_fold self init function =
wrapped builder value =
current = if builder.length == 0 then init else builder.last
builder.append (function current value)
built = self.fold (Vector.new_builder self.length) wrapped
built.to_vector
## Combines all the elements of a non-empty vector using a binary operation.
Arguments:
@ -1058,6 +1078,26 @@ type Builder
Panic.catch IndexOutOfBoundsException (self.java_builder.get actual_index) _->
Error.throw (Index_Out_Of_Bounds.Error index self.length)
## Get the first element from the vector, or an `Empty_Error` if the vector
is empty.
> Example
The following code returns 1.
[1, 2, 3, 4].first
first : Vector ! Index_Out_Of_Bounds
first self = self.at 0
## Get the last element of the vector, or an `Empty_Error` if the vector is
empty.
> Example
The following code returns 4.
[1, 2, 3, 4].last
last : Vector ! Index_Out_Of_Bounds
last self = self.at -1
## Checks whether a predicate holds for at least one element of this builder.
Arguments:

View File

@ -3,7 +3,8 @@ import project.Meta
@Builtin_Type
type Index_Out_Of_Bounds
## UNSTABLE
## PRIVATE
UNSTABLE
An error indicating that a requested index was out of bounds of a collection.
@ -21,7 +22,8 @@ type Index_Out_Of_Bounds
@Builtin_Type
type Syntax_Error
## The runtime representation of a syntax error.
## PRIVATE
The runtime representation of a syntax error.
Arguments:
- message: A description of the erroneous syntax.
@ -29,7 +31,8 @@ type Syntax_Error
@Builtin_Type
type Type_Error
## The runtime representation of a type error.
## PRIVATE
The runtime representation of a type error.
Arguments:
- expected: The expected type at the error location.
@ -39,7 +42,8 @@ type Type_Error
@Builtin_Type
type Compile_Error
## The runtime representation of a compilation error.
## PRIVATE
The runtime representation of a compilation error.
Arguments:
- message: A description of the erroneous state.
@ -47,7 +51,8 @@ type Compile_Error
@Builtin_Type
type Inexhaustive_Pattern_Match
## The error thrown when a there is no pattern to match on the scrutinee.
## PRIVATE
The error thrown when a there is no pattern to match on the scrutinee.
Arguments:
- scrutinee: The scrutinee that failed to match.
@ -55,7 +60,8 @@ type Inexhaustive_Pattern_Match
@Builtin_Type
type Arity_Error
## The error thrown when the number of arguments provided to an operation
## PRIVATE
The error thrown when the number of arguments provided to an operation
does not match the expected number of arguments.
Arguments:
@ -66,7 +72,8 @@ type Arity_Error
@Builtin_Type
type Uninitialized_State
## The error thrown when the program attempts to read from a state slot that has
## PRIVATE
The error thrown when the program attempts to read from a state slot that has
not yet been initialized.
Arguments:
@ -75,7 +82,8 @@ type Uninitialized_State
@Builtin_Type
type No_Such_Method
## The error thrown when the specified symbol does not exist as a method on
## PRIVATE
The error thrown when the specified symbol does not exist as a method on
the target.
Arguments:
@ -102,7 +110,8 @@ type No_Such_Method
@Builtin_Type
type Polyglot_Error
## An error that occurred across a polyglot boundary.
## PRIVATE
An error that occurred across a polyglot boundary.
Arguments:
- cause: A polyglot object corresponding to the original error.
@ -115,7 +124,8 @@ type Module_Not_In_Package_Error
@Builtin_Type
type Arithmetic_Error
## An error for when an erroneous arithmetic computation takes place.
## PRIVATE
An error for when an erroneous arithmetic computation takes place.
Arguments:
- message: A description of the error condition.
@ -123,7 +133,8 @@ type Arithmetic_Error
@Builtin_Type
type Invalid_Array_Index
## An error that occurs when a program requests a read from an array index
## PRIVATE
An error that occurs when a program requests a read from an array index
that is out of bounds in the array.
Arguments:
@ -133,7 +144,8 @@ type Invalid_Array_Index
@Builtin_Type
type Not_Invokable
## An error that occurs when an object is used as a function in a function
## PRIVATE
An error that occurs when an object is used as a function in a function
call, but it cannot be called.
Arguments:
@ -142,7 +154,8 @@ type Not_Invokable
@Builtin_Type
type Unsupported_Argument_Types
## An error that occurs when arguments used in a function call are invalid
## PRIVATE
An error that occurs when arguments used in a function call are invalid
types for the function.
Arguments:
@ -152,7 +165,8 @@ type Unsupported_Argument_Types
@Builtin_Type
type Module_Does_Not_Exist
## An error that occurs when the specified module cannot be found.
## PRIVATE
An error that occurs when the specified module cannot be found.
Arguments:
- name: The module searched for.
@ -160,7 +174,8 @@ type Module_Does_Not_Exist
@Builtin_Type
type Invalid_Conversion_Target
## An error that occurs when the specified value cannot be converted to a given type
## PRIVATE
An error that occurs when the specified value cannot be converted to a given type
Arguments:
- target: the type trying to be converted to.
@ -168,7 +183,8 @@ type Invalid_Conversion_Target
@Builtin_Type
type No_Such_Conversion
## An error that occurs when the conversion from one type to another does not exist
## PRIVATE
An error that occurs when the conversion from one type to another does not exist
Arguments:
- target: the type trying to be converted to.

View File

@ -164,7 +164,7 @@ export project.Network.URI.URI
export project.Random
from project.Data.Noise export all hiding Noise, Generator, Deterministic_Random, Long, Random
from project.Data.Statistics export all hiding to_moment_statistic, wrap_java_call, calculate_correlation_statistics, calculate_spearman_rank, calculate_correlation_statistics_matrix, Moments, MomentStatistic, CountMinMax, CorrelationStatistics, Rank, ClassCastException, NullPointerException
from project.Data.Statistics export all hiding to_moment_statistic, wrap_java_call, calculate_correlation_statistics, calculate_spearman_rank, calculate_correlation_statistics_matrix, compute_fold, empty_value, is_valid
from project.Data.Index_Sub_Range.Index_Sub_Range import First, Last
from project.Error.Problem_Behavior.Problem_Behavior import all

View File

@ -16,6 +16,9 @@ type HTTP_Method
## The HTTP method "PUT".
Put
## The HTTP method "PATCH".
Patch
## The HTTP method "DELETE".
Delete
@ -25,6 +28,9 @@ type HTTP_Method
## The HTTP method "CONNECT".
Connect
## Custom unsupported HTTP method.
Custom verb:Text
## Convert to a Text of the HTTP method name.
to_http_method_name : Text
to_http_method_name self = case self of
@ -33,6 +39,8 @@ type HTTP_Method
HTTP_Method.Head -> "HEAD"
HTTP_Method.Post -> "POST"
HTTP_Method.Put -> "PUT"
HTTP_Method.Patch -> "PATCH"
HTTP_Method.Delete -> "DELETE"
HTTP_Method.Trace -> "TRACE"
HTTP_Method.Connect -> "CONNECT"
HTTP_Method.Custom verb -> verb

View File

@ -106,11 +106,10 @@ write_file_backing_up_old_one file action = Panic.recover [File_Error.IO_Error,
Panic.rethrow <| new_file.move_to file
go 0
## PRIVATE
type Internal_Write_Operation_Panicked
## PRIVATE
Panic (cause : Caught_Panic)
## PRIVATE
type Internal_Write_Operation_Errored
## PRIVATE
Error (cause : Any)

View File

@ -634,7 +634,7 @@ type Table
descending order.
table.order_by (Sort_Column_Selector.By_Index [1, Sort_Column.Index -7 Sort_Direction.Descending])
order_by : Text | Vector Text | Sort_Column_Selector -> Text_Ordering -> Problem_Behavior -> Table ! Incomparable_Values
order_by : Text | Sort_Column | Vector (Text | Sort_Column) | Sort_Column_Selector -> Text_Ordering -> Problem_Behavior -> Table ! Incomparable_Values
order_by self (columns = (Sort_Column_Selector.By_Name [(Sort_Column.Name (self.columns.at 0 . name))])) text_ordering=Text_Ordering.Default on_problems=Report_Warning = Panic.handle_wrapped_dataflow_error <|
problem_builder = Problem_Builder.new
columns_for_ordering = Table_Helpers.prepare_order_by self.columns columns problem_builder

View File

@ -19,7 +19,6 @@ component-groups:
exports:
- Standard.Table.Data.Table.Table.at
- Standard.Table.Data.Table.Table.select_columns
- Standard.Table.Data.Table.Table.rename_columns
- Standard.Table.Data.Table.Table.remove_columns
- Standard.Table.Data.Table.Table.reorder_columns
- Standard.Table.Data.Table.Table.sort_columns
@ -29,8 +28,11 @@ component-groups:
- Standard.Table.Data.Table.Table.aggregate
- Standard.Base.Transform:
exports:
- Standard.Table.Data.Table.Table.rename_columns
- Standard.Table.Data.Table.Table.filter
- Standard.Table.Data.Table.Table.order_by
- Standard.Table.Data.Table.Table.to_csv
- Standard.Table.Data.Table.Table.transpose
- Standard.Table.Data.Table.Table.cross_tab
- Standard.Table.Data.Column.Column.to_table
- Standard.Base.Output:
exports:

View File

@ -613,7 +613,7 @@ type Table
table = Examples.inventory_table
table.order_by (Sort_Column_Selector.By_Name ["total_stock", Sort_Column.Name "sold_stock" Sort_Direction.Descending])
order_by : Text | Vector Text | Sort_Column_Selector -> Text_Ordering -> Problem_Behavior -> Table ! Incomparable_Values
order_by : Text | Sort_Column | Vector (Text | Sort_Column) | Sort_Column_Selector -> Text_Ordering -> Problem_Behavior -> Table ! Incomparable_Values
order_by self (columns = (Sort_Column_Selector.By_Name [(Sort_Column.Name (self.columns.at 0 . name))])) text_ordering=Text_Ordering.Default on_problems=Report_Warning =
problem_builder = Problem_Builder.new
columns_for_ordering = Table_Helpers.prepare_order_by self.columns columns problem_builder
@ -1221,7 +1221,7 @@ type Table
`Input_Indices_Already_Matched`, with the column included the first
time it is matched.
- If there are no columns to transpose, a `No_Input_Columns`.
transpose : Vector Text | Column_Selector -> Text -> Text -> Problem_Behavior -> Table
transpose : Text | Vector Text | Column_Selector -> Text -> Text -> Problem_Behavior -> Table
transpose self (id_fields = Column_Selector.By_Name []) (name_field="Name") (value_field="Value") (on_problems = Report_Warning) =
columns_helper = self.columns_helper
unique = Unique_Name_Strategy.new
@ -1271,7 +1271,7 @@ type Table
- If an aggregation fails, an `Invalid_Aggregation`.
- If when concatenating values there is an quoted delimited, an `Unquoted_Delimiter`
- If there are more than 10 issues with a single column, an `Additional_Warnings`.
cross_tab : Vector Text | Column_Selector -> (Text | Integer | Column) -> Vector Aggregate_Column -> Problem_Behavior -> Table
cross_tab : Text | Vector Text | Column_Selector -> (Text | Integer | Column) -> Vector Aggregate_Column -> Problem_Behavior -> Table
cross_tab self group_by=[] name_column=self.column_names.first values=Aggregate_Column.Count (on_problems=Report_Warning) =
columns_helper = self.columns_helper
problem_builder = Problem_Builder.new

View File

@ -2,10 +2,10 @@ from Standard.Base import all
polyglot java import org.enso.table.error.ColumnCountMismatchException
polyglot java import org.enso.table.error.ColumnNameMismatchException
## One or more columns not found in the input table.
Can occur when using By_Name or By_Column.
type Missing_Input_Columns
## PRIVATE
One or more columns not found in the input table.
Can occur when using By_Name or By_Column.
Error (criteria : [Text])
## PRIVATE
@ -15,9 +15,10 @@ type Missing_Input_Columns
to_display_text self =
"The criteria "+self.criteria.to_text+" did not match any columns."
## One or more column indexes were invalid on the input table.
Can occur when using By_Index.
type Column_Indexes_Out_Of_Range
## PRIVATE
One or more column indexes were invalid on the input table.
Can occur when using By_Index.
Error (indexes : [Integer])
## PRIVATE
@ -28,9 +29,10 @@ type Column_Indexes_Out_Of_Range
True -> "The index " + (self.indexes.at 0).to_text + " is out of range."
False -> "The indexes "+self.indexes.short_display_text+" are out of range."
## More names than the column count provided to the function.
Can occur when using By_Position.
type Too_Many_Column_Names_Provided
## PRIVATE
More names than the column count provided to the function.
Can occur when using By_Position.
Error (column_names : [Text])
## PRIVATE

View File

@ -44,6 +44,10 @@ make_filter_column source_column filter_condition = case filter_condition of
Value_Type.expect_text source_column.value_type <|
expect_column_or_value_as_text "substring" substring <|
source_column.contains substring
Not_Contains substring ->
Value_Type.expect_text source_column.value_type <|
expect_column_or_value_as_text "substring" substring <|
source_column.contains substring . not
Is_Empty ->
Value_Type.expect_text source_column.value_type <|
source_column.is_empty

View File

@ -1,6 +1,7 @@
from Standard.Base import all
import Standard.Base.Data.Text.Matching
import Standard.Base.Data.Ordering.Vector_Lexicographic_Order
import Standard.Base.Error.Illegal_Argument.Illegal_Argument
import Standard.Base.Error.Illegal_State.Illegal_State
import project.Data.Column_Name_Mapping.Column_Name_Mapping
@ -137,8 +138,10 @@ type Table_Column_Helper
criterion on the list. If a single criterion's group has more than one
element, their relative order is the same as in the input.
- problem_builder: Encapsulates the aggregation of encountered problems.
select_columns_helper : Vector | Column_Selector -> Boolean -> Problem_Builder -> Vector
select_columns_helper : Text | Vector | Column_Selector -> Boolean -> Problem_Builder -> Vector
select_columns_helper self selector reorder problem_builder = case selector of
_ : Text ->
self.select_columns_helper (Column_Selector.By_Name [selector]) reorder problem_builder
_ : Vector ->
self.select_columns_helper (Column_Selector.By_Name selector) reorder problem_builder
Column_Selector.By_Name names matcher ->
@ -406,24 +409,32 @@ type Column_Transform_Element
Value column associated_selector
## PRIVATE
prepare_order_by : Vector -> Text | Vector Text | Sort_Column_Selector -> Problem_Builder -> Vector Column_Transform_Element
prepare_order_by : Vector -> Text | Sort_Column | Vector (Text | Sort_Column) | Sort_Column_Selector -> Problem_Builder -> Vector Column_Transform_Element
prepare_order_by internal_columns column_selectors problem_builder =
selected_elements = case column_selectors of
_ : Text ->
unified_name_selectors = [Sort_Column.Name column_selectors]
select_columns_by_name internal_columns unified_name_selectors Text_Matcher.Case_Sensitive problem_builder name_extractor=(_.name)
Sort_Column.Name _ _ -> select_columns_by_name internal_columns [column_selectors] Text_Matcher.Case_Sensitive problem_builder name_extractor=(_.name)
Sort_Column.Index _ _ -> select_columns_by_index internal_columns [column_selectors] problem_builder index_extractor=(_.index)
Sort_Column.Column _ _ -> select_columns_by_column_reference internal_columns [column_selectors] problem_builder column_extractor=(_.column)
_ : Vector ->
unified_name_selectors = column_selectors.map (Sort_Column.Name _)
unified_name_selectors = column_selectors.map selector-> case selector of
_ : Text -> Sort_Column.Name selector
Sort_Column.Name _ _ -> selector
_ -> Error.throw (Illegal_Argument.Error "Invalid column selector passed to order_by. Only Text and Sort_Column.Name are allowed as a Vector.")
select_columns_by_name internal_columns unified_name_selectors Text_Matcher.Case_Sensitive problem_builder name_extractor=(_.name)
Sort_Column_Selector.By_Name name_selectors matcher ->
unified_name_selectors = name_selectors.map selector-> case selector of
_ : Text -> Sort_Column.Name selector
Sort_Column.Name _ _ -> selector
_ -> Error.throw (Illegal_Argument.Error "Invalid column selector passed to order_by. Only Text and Sort_Column.Name are allowed for Sort_Column_Selector.By_Name.")
select_columns_by_name internal_columns unified_name_selectors matcher problem_builder name_extractor=(_.name)
Sort_Column_Selector.By_Index index_selectors ->
unified_index_selectors = index_selectors.map selector-> case selector of
_ : Integer -> Sort_Column.Index selector
Sort_Column.Index _ _ -> selector
_ -> Error.throw (Illegal_Argument.Error "Invalid column selector passed to order_by. Only Integer and Sort_Column.Index are allowed for Sort_Column_Selector.By_Index.")
select_columns_by_index internal_columns unified_index_selectors problem_builder index_extractor=(_.index)
Sort_Column_Selector.By_Column column_selectors ->
unified_column_selectors = column_selectors.map selector-> case selector of

View File

@ -159,11 +159,12 @@ public final class ParseStdLibTest extends TestCase {
Arrays.asList(
// Files containing type expressions not supported by old parser.
"Data/Index_Sub_Range.enso",
"Error/Common.enso",
"Data/Text/Regex/Regex_Mode.enso",
"Internal/Base_Generator.enso",
"Data/Pair.enso",
"Data/Sort_Column_Selector.enso",
"Data/Value_Type.enso"));
"Data/Text/Regex/Regex_Mode.enso",
"Data/Value_Type.enso",
"Error/Common.enso",
"Internal/Base_Generator.enso"));
}
private static boolean isKnownToWork(String name) {

View File

@ -1,52 +1,35 @@
package org.enso.base.statistics;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.function.BiFunction;
import java.util.stream.Stream;
import org.graalvm.polyglot.Value;
public class CountMinMax {
private static boolean isValid(Object v) {
return !(v == null || (v instanceof Double && Double.isNaN((Double) v)));
public long count;
public boolean comparatorError;
public Value minimum;
public Value maximum;
public CountMinMax() {
this.count = 0;
this.comparatorError = false;
this.minimum = Value.asValue(null);
this.maximum = Value.asValue(null);
}
public static Stream<Object> toObjectStream(Object[] array) {
return Arrays.stream(array);
public void increment() {
this.count++;
}
public final int count;
public final boolean comparatorError;
public final Object minimum;
public final Object maximum;
public void failComparator() {
this.comparatorError = true;
this.minimum = Value.asValue(null);
this.maximum = Value.asValue(null);
}
public CountMinMax(Stream<Object> values, Comparator<Object> objectComparator) {
int count = 0;
public void setMinimum(Value value) {
this.minimum = value;
}
boolean comparatorFailed = false;
Object minimum = null;
Object maximum = null;
Iterator<Object> iterator = values.filter(CountMinMax::isValid).iterator();
while (iterator.hasNext()) {
Object value = iterator.next();
count++;
if (!comparatorFailed) {
try {
minimum =
minimum == null || objectComparator.compare(minimum, value) > 0 ? value : minimum;
maximum =
maximum == null || objectComparator.compare(maximum, value) < 0 ? value : maximum;
} catch (ClassCastException e) {
comparatorFailed = true;
}
}
}
this.count = count;
this.comparatorError = comparatorFailed;
this.minimum = comparatorFailed ? null : minimum;
this.maximum = comparatorFailed ? null : maximum;
public void setMaximum(Value value) {
this.maximum = value;
}
}

View File

@ -1,7 +1,5 @@
package org.enso.base.statistics;
import java.util.Arrays;
/** Set of descriptive statistics for numerical data sets */
public class Moments {
@ -32,38 +30,31 @@ public class Moments {
/** Statistic to compute the sample kurtosis of the values. */
public static final MomentStatistic KURTOSIS = new Kurtosis();
private long count;
private double[] totals;
/**
* Compute a set of statistics on a data set.
* Create a new instance.
*
* @param data set of values.
* @param statistics set of statistics to compute.
* @return computed statistics.
* @param order the maximum order of moments to compute.
*/
public static double[] compute(Double[] data, MomentStatistic[] statistics) {
if (statistics.length == 0) {
return new double[0];
public Moments(int order) {
this.count = 0;
this.totals = new double[order];
}
public Moments add(double value) {
count++;
double v = value;
for (int i = 0; i < totals.length; i++) {
totals[i] += v;
v *= value;
}
int order = Arrays.stream(statistics).mapToInt(s -> s == null ? 0 : s.order()).max().getAsInt();
return this;
}
long count = 0;
double[] totals = new double[order];
for (Double value : data) {
if (value == null || Double.isNaN(value)) {
continue;
}
count++;
double v = value;
for (int i = 0; i < order; i++) {
totals[i] += v;
v *= value;
}
}
final long _count = count;
return Arrays.stream(statistics)
.mapToDouble(s -> s == null ? Double.NaN : s.evaluate(_count, totals))
.toArray();
public double compute(MomentStatistic s) {
return s.evaluate(count, totals);
}
}

View File

@ -34,7 +34,6 @@ bench =
Bench.measure (random_vec.filter (x -> x % 3 == 1)) "Filter" iter_size num_iterations
Bench.measure (random_vec.filter_with_index (i-> x-> (i+x) % 3 == 1)) "Filter With Index" iter_size num_iterations
random_gen = Random.new 0
Bench.measure (random_vec . map (x -> x + random_gen.nextLong) . filter (x -> x % 3 == 1)) "Map & Filter" iter_size num_iterations
Bench.measure (random_vec.partition (x -> x % 3 == 1)) "Partition" iter_size num_iterations
Bench.measure (random_vec.partition_with_index (i-> x-> (i+x) % 3 == 1)) "Partition With Index" iter_size num_iterations

View File

@ -79,15 +79,17 @@ spec setup =
t.filter "X" (Filter_Condition.Between (t.at "Y") "bzzzz") . at "X" . to_vector . should_equal ["abb", "baca", "b"]
Test.specify "by text search (contains, starts_with, ends_with, like)" <|
t = table_builder [["ix", [1, 2, 3, 4, 5]], ["X", ["abb", "baca", "banana", Nothing, "nana"]], ["Y", ["a", "b", "b", "c", "a"]], ["Z", ["aaaaa", "bbbbb", "[ab]", "[ab]aaaa", "[ab]ccc"]]]
t = table_builder [["ix", [1, 2, 3, 4, 5]], ["X", ["abb", "baca", "banana", Nothing, "nana"]], ["Y", ["a", "b", "d", "c", "a"]], ["Z", ["aaaaa", "bbbbb", "[ab]", "[ab]aaaa", "[ab]ccc"]]]
t.filter "X" (Filter_Condition.Starts_With "ba") on_problems=Report_Error . at "X" . to_vector . should_equal ["baca", "banana"]
t.filter "X" (Filter_Condition.Ends_With "na") on_problems=Report_Error . at "X" . to_vector . should_equal ["banana", "nana"]
t.filter "X" (Filter_Condition.Contains "ac") on_problems=Report_Error . at "X" . to_vector . should_equal ["baca"]
t.filter "X" (Filter_Condition.Not_Contains "ac") on_problems=Report_Error . at "X" . to_vector . should_equal ["abb", "banana", "nana"]
t.filter "X" (Filter_Condition.Starts_With (t.at "Y")) on_problems=Report_Error . at "X" . to_vector . should_equal ["abb", "baca", "banana"]
t.filter "X" (Filter_Condition.Starts_With (t.at "Y")) on_problems=Report_Error . at "X" . to_vector . should_equal ["abb", "baca"]
t.filter "X" (Filter_Condition.Ends_With (t.at "Y")) on_problems=Report_Error . at "X" . to_vector . should_equal ["nana"]
t.filter "X" (Filter_Condition.Contains (t.at "Y")) on_problems=Report_Error . at "X" . to_vector . should_equal ["abb", "baca", "banana", "nana"]
t.filter "X" (Filter_Condition.Contains (t.at "Y")) on_problems=Report_Error . at "X" . to_vector . should_equal ["abb", "baca", "nana"]
t.filter "X" (Filter_Condition.Not_Contains (t.at "Y")) on_problems=Report_Error . at "X" . to_vector . should_equal ["banana"]
t.filter "X" (Filter_Condition.Like "%an%") on_problems=Report_Error . at "X" . to_vector . should_equal ["banana", "nana"]
t.filter "X" (Filter_Condition.Like "_a%") on_problems=Report_Error . at "X" . to_vector . should_equal ["baca", "banana", "nana"]
@ -109,6 +111,7 @@ spec setup =
t.filter "X" (Filter_Condition.Ends_With '\nb') on_problems=Report_Error . at "X" . to_vector . should_equal ['a\n\n\nb', 'a\nb']
t.filter "X" (Filter_Condition.Ends_With '\n') on_problems=Report_Error . at "X" . to_vector . should_equal ['a\n\n\n', 'a\n']
t.filter "X" (Filter_Condition.Starts_With 'c') on_problems=Report_Error . at "X" . to_vector . should_equal ['caa\nbb']
t.filter "X" (Filter_Condition.Not_Contains '\nb') on_problems=Report_Error . at "X" . to_vector . should_equal ['a\n\n\n', 'a\n']
if test_selection.supports_unicode_normalization then
t = table_builder [["X", ['śnieg', 's\u0301nieg', 'X', Nothing, 'połać', 'połac\u0301']]]
@ -117,6 +120,7 @@ spec setup =
t.filter "X" (Filter_Condition.Contains 'ś') on_problems=Report_Error . at "X" . to_vector . should_equal ['śnieg', 's\u0301nieg']
t.filter "X" (Filter_Condition.Ends_With 'ś') on_problems=Report_Error . at "X" . to_vector . should_equal []
t.filter "X" (Filter_Condition.Ends_With 'ć') on_problems=Report_Error . at "X" . to_vector . should_equal ['połać', 'połac\u0301']
t.filter "X" (Filter_Condition.Not_Contains 'ś') on_problems=Report_Error . at "X" . to_vector . should_equal ['X', 'połać', 'połac\u0301']
# This should be replaced with the disabled test below, once the related bug is fixed.
t.filter "X" (Filter_Condition.Like 'ś%') on_problems=Report_Error . at "X" . to_vector . should_equal ['śnieg']
@ -147,12 +151,14 @@ spec setup =
check_column_type_error_handling (t.filter "X" (Filter_Condition.Contains (t.at "ix")) on_problems=_)
check_column_type_error_handling (t.filter "X" (Filter_Condition.Like (t.at "ix")) on_problems=_)
check_column_type_error_handling (t.filter "X" (Filter_Condition.Not_Like (t.at "ix")) on_problems=_)
check_column_type_error_handling (t.filter "X" (Filter_Condition.Not_Contains (t.at "ix")) on_problems=_)
check_column_type_error_handling (t.filter "ix" (Filter_Condition.Starts_With "A") on_problems=_)
check_column_type_error_handling (t.filter "ix" (Filter_Condition.Ends_With "A") on_problems=_)
check_column_type_error_handling (t.filter "ix" (Filter_Condition.Contains "A") on_problems=_)
check_column_type_error_handling (t.filter "ix" (Filter_Condition.Like "A") on_problems=_)
check_column_type_error_handling (t.filter "ix" (Filter_Condition.Not_Like "A") on_problems=_)
check_column_type_error_handling (t.filter "ix" (Filter_Condition.Not_Contains "A") on_problems=_)
check_column_type_error_handling (t.filter "ix" Filter_Condition.Is_Empty on_problems=_)
check_column_type_error_handling (t.filter "ix" Filter_Condition.Not_Empty on_problems=_)
@ -166,6 +172,7 @@ spec setup =
check_scalar_type_error_handling "substring" (t.filter "X" (Filter_Condition.Contains 42) on_problems=_)
check_scalar_type_error_handling "pattern" (t.filter "X" (Filter_Condition.Like 42) on_problems=_)
check_scalar_type_error_handling "pattern" (t.filter "X" (Filter_Condition.Not_Like 42) on_problems=_)
check_scalar_type_error_handling "substring" (t.filter "X" (Filter_Condition.Not_Contains 42) on_problems=_)
Test.specify "by nulls" <|
t = table_builder [["ix", [1, 2, 3, 4]], ["X", [Nothing, 1, Nothing, 4]]]
@ -265,4 +272,3 @@ spec setup =
table.at "X" . to_vector . should_equal (t.at "X" . to_vector)
problems = [Index_Out_Of_Bounds.Error 4 1]
Problems.test_problem_handling action problems tester

View File

@ -35,15 +35,33 @@ spec setup =
t1.at "alpha" . to_vector . should_equal [0, 1, 2, 3]
t1.at "gamma" . to_vector . should_equal [4, 3, 2, 1]
## Assumes stable sorting on database engine.
t2 = table.order_by (Sort_Column_Selector.By_Index [1, Sort_Column.Index -8 Sort_Direction.Descending])
t2.at "beta" . to_vector . should_equal ["a", "a", "b", "b"]
t2.at "gamma" . to_vector . should_equal [3, 1, 4, 2]
t2.at "alpha" . to_vector . should_equal [1, 3, 0, 2]
Test.specify "should work with single column name" <|
t1 = table.order_by "alpha"
t1.at "alpha" . to_vector . should_equal [0, 1, 2, 3]
t1.at "gamma" . to_vector . should_equal [4, 3, 2, 1]
t2 = table.order_by (Sort_Column_Selector.By_Index [1, Sort_Column.Index -8 Sort_Direction.Descending])
t2.at "beta" . to_vector . should_equal ["a", "a", "b", "b"]
t2.at "gamma" . to_vector . should_equal [3, 1, 4, 2]
t2.at "alpha" . to_vector . should_equal [1, 3, 0, 2]
Test.specify "should work with single Sort_Column" <|
t1 = table.order_by (Sort_Column.Name "alpha")
t1.at "alpha" . to_vector . should_equal [0, 1, 2, 3]
t1.at "gamma" . to_vector . should_equal [4, 3, 2, 1]
t2 = t1.order_by (Sort_Column.Name "alpha" Sort_Direction.Descending)
t2.at "alpha" . to_vector . should_equal [3, 2, 1, 0]
t2.at "gamma" . to_vector . should_equal [1, 2, 3, 4]
t3 = table.order_by (Sort_Column.Index 0)
t3.at "alpha" . to_vector . should_equal [0, 1, 2, 3]
t3.at "gamma" . to_vector . should_equal [4, 3, 2, 1]
t4 = t3.order_by (Sort_Column.Index 0 Sort_Direction.Descending)
t4.at "alpha" . to_vector . should_equal [3, 2, 1, 0]
t4.at "gamma" . to_vector . should_equal [1, 2, 3, 4]
Test.specify "should correctly handle regexes matching multiple names" <|
t1 = table.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name ".*ta" Sort_Direction.Descending] (Regex_Matcher.Value case_sensitivity=Case_Sensitivity.Sensitive))
@ -155,6 +173,11 @@ spec setup =
t1.at "alpha" . to_vector . should_equal [1, 3, 0, 2]
t1.at "gamma" . to_vector . should_equal [3, 1, 4, 2]
t1a = table.order_by ["beta", Sort_Column.Name "alpha" Sort_Direction.Ascending]
t1a.at "beta" . to_vector . should_equal ["a", "a", "b", "b"]
t1a.at "alpha" . to_vector . should_equal [1, 3, 0, 2]
t1a.at "gamma" . to_vector . should_equal [3, 1, 4, 2]
t2 = table.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name "beta", Sort_Column.Name "alpha" Sort_Direction.Descending])
t2.at "beta" . to_vector . should_equal ["a", "a", "b", "b"]
t2.at "alpha" . to_vector . should_equal [3, 1, 2, 0]

View File

@ -340,26 +340,6 @@ spec =
i.at "Storage Type" . to_vector . should_equal [Storage.Text, Storage.Integer, Storage.Any]
Test.group "Sorting Tables" <|
df = (enso_project.data / "clothes.csv").read
Test.specify "should allow sorting by a single column name" <|
r_1 = df.order_by (Sort_Column_Selector.By_Name ["Quantity"])
r_1.at 'Id' . to_vector . should_equal [2,4,1,3,5,6]
r_3 = df.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name "Rating" Sort_Direction.Descending])
r_3.at 'Id' . to_vector . should_equal [3,1,4,5,2,6]
Test.specify 'should allow sorting by multiple column names' <|
r_1 = df.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name 'Quantity', 'Rating'])
r_1.at 'Id' . to_vector . should_equal [2,4,1,3,6,5]
r_2 = df.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name 'Rating' Sort_Direction.Descending, Sort_Column.Name 'Quantity' Sort_Direction.Descending])
r_2.at 'Id' . to_vector . should_equal [3,1,4,5,6,2]
Test.specify 'should allow sorting with specific by-column rules' <|
r_1 = df.order_by (Sort_Column_Selector.By_Name ["Quantity", Sort_Column.Name "Price" Sort_Direction.Descending])
r_1.at 'Id' . to_vector . should_equal [4,2,3,1,6,5]
Test.specify 'should respect defined comparison operations for custom types' <|
c_1 = ['id', [1, 2, 3, 4, 5, 6]]
c_2 = ['val', [My.Data 1 2, My.Data 3 4, My.Data 2 1, My.Data 5 2, My.Data 7 0, My.Data 4 -1]]
@ -367,13 +347,6 @@ spec =
r = df.order_by (Sort_Column_Selector.By_Name ['val'])
r.at 'id' . to_vector . should_equal [1,3,6,2,4,5]
Test.specify 'should return warnings and errors when passed a non-existent column' <|
action = df.order_by (Sort_Column_Selector.By_Name ['foobar']) on_problems=_
tester table =
table.at 'Id' . to_vector . should_equal [1,2,3,4,5,6]
problems = [Missing_Input_Columns.Error [Sort_Column.Name 'foobar'], No_Input_Columns_Selected]
Problems.test_problem_handling action problems tester
Test.specify 'should correctly reorder all kinds of columns and leave the original columns untouched' <|
ord = [0, 3, 2, 4, 1]
ints = [1, 2, 3, 4, 5]
@ -1012,6 +985,15 @@ spec =
t1.at "Name" . to_vector . should_equal ["Value", "Another", "Yet Another", "Value", "Another", "Yet Another", "Value", "Another", "Yet Another"]
t1.at "Value" . to_vector . should_equal [1, 10, Nothing, 2, Nothing, "Hello", 3, 20, "World"]
Test.specify "should allow single id field" <|
t = Table.new [["Key", ["x", "y", "z"]], ["Value", [1, 2, 3]], ["Another", [10, Nothing, 20]], ["Yet Another", [Nothing, "Hello", "World"]]]
t1 = t.transpose "Key"
t1.row_count . should_equal 9
t1.column_count . should_equal 3
t1.at "Key" . to_vector . should_equal ["x", "x", "x", "y", "y", "y", "z", "z", "z"]
t1.at "Name" . to_vector . should_equal ["Value", "Another", "Yet Another", "Value", "Another", "Yet Another", "Value", "Another", "Yet Another"]
t1.at "Value" . to_vector . should_equal [1, 10, Nothing, 2, Nothing, "Hello", 3, 20, "World"]
Test.specify "should allow all id fields with warning or error" <|
t = Table.new [["Key", ["x", "y", "z"]], ["Value", [1, 2, 3]], ["Another", [10, Nothing, 20]], ["Yet Another", [Nothing, "Hello", "World"]]]
t1 = t.transpose t.column_names
@ -1072,6 +1054,16 @@ spec =
t1.at "y" . to_vector . should_equal [2, 1]
t1.at "z" . to_vector . should_equal [1, 1]
Test.specify "should allow a grouping by text" <|
t = Table.new [["Group", ["A","B","A","B","A","B","A","B","A"]], ["Key", ["x", "x", "x", "x", "y", "y", "y", "z", "z"]], ["Value", [1, 2, 3, 4, 5, 6, 7, 8, 9]]]
t1 = t.cross_tab "Group" "Key"
t1.row_count . should_equal 2
t1.column_count . should_equal 4
t1.at "Group" . to_vector . should_equal ["A", "B"]
t1.at "x" . to_vector . should_equal [2, 2]
t1.at "y" . to_vector . should_equal [2, 1]
t1.at "z" . to_vector . should_equal [1, 1]
Test.specify "should aggregate if name_field not found" <|
t = Table.new [["Key", ["x", "x", "x", "x", "y", "y", "y", "z", "z"]], ["Value", [1, 2, 3, 4, 5, 6, 7, 8, 9]]]
t1 = t.cross_tab [] "Name"

View File

@ -1,4 +1,6 @@
from Standard.Base import all
import Standard.Base.Error.Common.Index_Out_Of_Bounds
import Standard.Base.Error.Illegal_Argument.Illegal_Argument
from Standard.Base.Data.Json import Json_Parse_Error, No_Such_Field
from Standard.Test import Test, Test_Suite
@ -34,7 +36,6 @@ Text.should_render_itself self =
spec =
Test.group "JSON Deserialization" <|
Test.specify "should parse JSON structures" <|
"0 ".should_parse_as 0
" 123 ".should_parse_as 123
@ -88,7 +89,6 @@ spec =
domain.should_equal books
Test.group "JSON Serialization" <|
Test.specify "should print JSON structures to valid json" <|
"0".should_render_itself
"123".should_render_itself
@ -117,8 +117,12 @@ spec =
fields = Map.empty . insert "type" t . insert "name" n . insert "year_of_birth" y
Json.Object fields
Test.group "JSON" <|
Test.specify "should render NaN and Infinity to null" <|
Number.nan.to_json.to_text . should_equal "null"
Number.positive_infinity.to_json.to_text . should_equal "null"
Number.negative_infinity.to_json.to_text . should_equal "null"
Test.group "JSON" <|
Test.specify "should allow getting object fields" <|
object = Json.parse '''
{ "foo": "bar",
@ -126,6 +130,42 @@ spec =
"y": {"z": null, "w": null} }
object.get "foo" . should_equal (Json.String "bar")
object.get_or_else "foo" . should_equal (Json.String "bar")
object.get "bar" . should_fail_with No_Such_Field.Error
object.get_or_else "bar" . should_equal Json.Null
object.get_or_else "bar" 1 . should_equal 1
Json.Null.get "foo" . should_fail_with No_Such_Field.Error
Json.Null.get_or_else "foo" . should_equal Json.Null
Json.Null.get_or_else "foo" 1 . should_equal 1
Test.specify "should be able to get field_names" <|
Json.parse '{ "foo": "bar", "baz": ["foo", "x", false] }' . field_names . should_equal ["baz", "foo"]
Json.parse '{}' . field_names . should_equal []
Json.parse 'null' . field_names . should_fail_with Illegal_Argument.Error
Json.parse '[1,2,3]' . field_names . should_fail_with Illegal_Argument.Error
Test.specify "should be able to get a value by index" <|
Json.parse "[1, 2, 3, 4, 5]" . at 2 . should_equal (Json.Number 3)
Json.parse "[1, 2, 3, 4, 5]" . at -2 . should_equal (Json.Number 4)
Json.parse "[1, 2, 3, 4, 5]" . at 5 . should_fail_with Index_Out_Of_Bounds.Error
Json.parse '"foo"' . at 0 . should_equal (Json.String "f")
Json.parse '"foo"' . at -1 . should_equal (Json.String "o")
Json.parse '"foo"' . at 3 . should_fail_with Index_Out_Of_Bounds.Error
Json.parse '{}' . at 1 . should_fail_with Illegal_Argument.Error
Test.specify "should be able to make empty objects and array" <|
Json.empty_object.should_equal (Json.Object Map.empty)
Json.empty_object.to_text.should_equal "{}"
Json.empty_array.should_equal (Json.Array [])
Json.empty_array.to_text.should_equal "[]"
Test.specify "should be able to get length" <|
Json.empty_object.length.should_equal 0
Json.empty_array.length.should_equal 0
Json.parse '{ "foo": "bar", "baz": ["foo", "x", false] }' . length . should_equal 2
Json.parse '[1, 2, 3, 4, 5]' . length . should_equal 5
Json.parse '"foo"' . length . should_equal 3
Json.parse '""' . length . should_equal 0
Json.Null.length.should_fail_with Illegal_Argument.Error
main = Test_Suite.run_main spec

View File

@ -69,6 +69,8 @@ spec = Test.group "List" <|
txt = ["aaa", "bbb", "abab", "cccc", "baaa", "ś"].to_list
txt.filter (Filter_Condition.Contains "a") . should_equal ["aaa", "abab", "baaa"].to_list
txt.filter (Filter_Condition.Contains 's\u0301') . should_equal ["ś"].to_list
txt.filter (Filter_Condition.Not_Contains "a") . should_equal ["bbb", "cccc", "ś"].to_list
txt.filter (Filter_Condition.Not_Contains 's\u0301') . should_equal ["aaa", "bbb", "abab", "cccc", "baaa"].to_list
txt.filter (Filter_Condition.Starts_With "a") . should_equal ["aaa", "abab"].to_list
txt.filter (Filter_Condition.Ends_With "a") . should_equal ["aaa", "baaa"].to_list
txt.filter (Filter_Condition.Less than="a") . should_equal List.Nil

View File

@ -286,6 +286,9 @@ spec =
1.0%0 . is_nan . should_be_true
almost_max_long_times_three%0.0 . is_nan . should_be_true
1/0 . is_infinite . should_be_true
-1/0 . is_infinite . should_be_true
Test.specify "should support less than operator" <|
(1 < 2).should_be_true
(1 < 1).should_be_false
@ -440,6 +443,11 @@ spec =
Number.positive_infinity.is_nan . should_be_false
Number.negative_infinity.is_nan . should_be_false
Number.nan.is_infinite . should_be_false
0.is_infinite . should_be_false
Number.positive_infinity.is_infinite . should_be_true
Number.negative_infinity.is_infinite . should_be_true
Number.nan==Number.nan . should_be_false
Number.nan==0 . should_be_false
Number.nan!=Number.nan . should_be_true

View File

@ -1,4 +1,5 @@
from Standard.Base import all
import Standard.Base.Error.Common.Type_Error
from Standard.Test import Test, Test_Suite
import Standard.Test.Extensions
@ -64,4 +65,9 @@ spec =
Ordering.Greater.and_then Ordering.Equal . should_equal Ordering.Greater
Ordering.Greater.and_then Ordering.Greater . should_equal Ordering.Greater
Test.specify "should fail with Type_Error for wrong type of that" <|
Ordering.Less.compare_to 1 . should_fail_with Type_Error.Error
Ordering.Less.compare_to Nothing . should_fail_with Type_Error.Error
Ordering.Less.compare_to "Hello" . should_fail_with Type_Error.Error
main = Test_Suite.run_main spec

View File

@ -0,0 +1,23 @@
from Standard.Base import all
import Standard.Base.Error.Common.Index_Out_Of_Bounds
from Standard.Test import Test, Test_Suite
import Standard.Test.Extensions
spec = Test.group "Pair" <|
Test.specify "should be created by new" <|
Pair.new 1 2 . should_equal (Pair.Value 1 2)
Test.specify "should allow mapping" <|
Pair.new 1 2 . map x->x+1 . should_equal (Pair.Value 2 3)
Test.specify "should act as a length 2 Vector" <|
Pair.new "A" "B" . length . should_equal 2
Pair.new "A" "B" . at 0 . should_equal "A"
Pair.new "A" "B" . at -2 . should_equal "A"
Pair.new "A" "B" . at 1 . should_equal "B"
Pair.new "A" "B" . at -1 . should_equal "B"
Pair.new "A" "B" . at 2 . should_fail_with Index_Out_Of_Bounds.Error
Pair.new "A" "B" . to_vector . should_equal ["A", "B"]
main = Test_Suite.run_main spec

View File

@ -125,6 +125,10 @@ spec = Test.group "Range" <|
vec_mut_2.to_vector . should_equal [Pair.new 0 5, Pair.new 1 7, Pair.new 2 9]
Test.specify "should be able to be folded" <|
1.up_to 6 . fold 0 (+) . should_equal 15
1.up_to 1 . fold 123 (+) . should_equal 123
Test.specify "should be able to perform a running fold" <|
1.up_to 6 . running_fold 0 (+) . should_equal [1, 3, 6, 10, 15]
1.up_to 1 . running_fold 123 (+) . should_equal []
Test.specify "should check all" <|
1.up_to 10 . all (> 0) . should_be_true
1.up_to 10 . all (< 0) . should_be_false

View File

@ -119,6 +119,14 @@ spec =
values = number_set.compute_bulk stats
vector_compare values expected
Test.specify "should allow running computation" <|
number_set.running . should_equal [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
expected_counts = [1, 2, 3, 4, 4, 5, 6, 7, 8, 8, 9, 10, 11, 12, 12, 13, 14, 15, 16, 16]
expected_sums = [0.4, -18.16, -35.15, -51.58, -51.58, -38.14, -44.99, -35.31, -43.86, -43.86, -33.48, 0.37, -40.65, -38.78, -38.78, -52.65, -91.71, -65.79, -81.8, -81.8]
missing_set.running . should_equal expected_counts
values = missing_set.running Statistic.Sum
vector_compare values expected_sums
Test.group "Statistics - empty Vector " <|
Test.specify "should be able to count and sum on empty Vector" <|
[].compute . should_equal 0
@ -145,6 +153,7 @@ spec =
text_set.compute Statistic.Variance . should_fail_with Illegal_Argument.Error
text_set.compute Statistic.Skew . should_fail_with Illegal_Argument.Error
text_set.compute Statistic.Kurtosis . should_fail_with Illegal_Argument.Error
text_set.running Statistic.Sum . should_fail_with Illegal_Argument.Error
Test.specify "should be able to do Count, Minimum and Maximum on custom type with compare_to" <|
ord_set.compute . should_equal 3

View File

@ -1,4 +1,5 @@
from Standard.Base import all
import Standard.Base.Error.Common.Type_Error
import Standard.Base.Error.Time_Error.Time_Error
from Standard.Test import Test, Test_Suite
@ -74,8 +75,8 @@ spec =
(duration - period).should_fail_with Time_Error.Error
(period + duration).should_fail_with Time_Error.Error
(period - duration).should_fail_with Time_Error.Error
(duration > period).should_fail_with Time_Error.Error
(duration < period).should_fail_with Time_Error.Error
(duration > period).should_fail_with Type_Error.Error
(duration < period).should_fail_with Type_Error.Error
Test.specify "Date_Time supports adding and subtracting Duration" <|
((Date_Time.new 2022 10 1 hour=10) + (Duration.new hours=2)) . should_equal (Date_Time.new 2022 10 1 hour=12)

View File

@ -113,6 +113,11 @@ spec = Test.group "Vectors" <|
Test.specify "should allow folding an operator over its elements" <|
[1,2,3].fold 0 (+) . should_equal 6
[].fold 123 (+) . should_equal 123
Test.specify "should allow a running fold operator over its elements" <|
[1,2,3].running_fold 0 (+) . should_equal [1, 3, 6]
[].running_fold 123 (+) . should_equal []
Test.specify "should allow to reduce elements if it is non-empty" <|
[1,2,3].reduce (+) . should_equal 6
@ -187,6 +192,8 @@ spec = Test.group "Vectors" <|
txtvec = ["aaa", "bbb", "abab", "cccc", "baaa", "ś"]
txtvec.filter (Filter_Condition.Contains "a") . should_equal ["aaa", "abab", "baaa"]
txtvec.filter (Filter_Condition.Contains 's\u0301') . should_equal ["ś"]
txtvec.filter (Filter_Condition.Not_Contains "a") . should_equal ["bbb", "cccc", "ś"]
txtvec.filter (Filter_Condition.Not_Contains 's\u0301') . should_equal ["aaa", "bbb", "abab", "cccc", "baaa"]
txtvec.filter (Filter_Condition.Starts_With "a") . should_equal ["aaa", "abab"]
txtvec.filter (Filter_Condition.Ends_With "a") . should_equal ["aaa", "baaa"]
txtvec.filter (Filter_Condition.Less than="a") . should_equal []
@ -216,6 +223,7 @@ spec = Test.group "Vectors" <|
txt3 = ['śnieg', 's\u0301nieg', 'X', 'połać', 'połac\u0301']
txt3.filter (Filter_Condition.Starts_With 'ś') . should_equal ['śnieg', 's\u0301nieg']
txt3.filter (Filter_Condition.Contains 'ś') . should_equal ['śnieg', 's\u0301nieg']
txt3.filter (Filter_Condition.Not_Contains 'ś') . should_equal ['X', 'połać', 'połac\u0301']
txt3.filter (Filter_Condition.Ends_With 'ś') . should_equal []
txt3.filter (Filter_Condition.Ends_With 'ć') . should_equal ['połać', 'połac\u0301']
## There is a bug with Java Regex in Unicode normalized mode (CANON_EQ) with quoting.

View File

@ -39,6 +39,7 @@ import project.Data.Ordering_Spec
import project.Data.Ordering.Comparator_Spec
import project.Data.Ordering.Natural_Order_Spec
import project.Data.Ordering.Vector_Lexicographic_Order_Spec
import project.Data.Pair_Spec
import project.Data.Range_Spec
import project.Data.Ref_Spec
import project.Data.Time.Spec as Time_Spec
@ -117,6 +118,7 @@ main = Test_Suite.run_main <|
Process_Spec.spec
Python_Interop_Spec.spec
R_Interop_Spec.spec
Pair_Spec.spec
Range_Spec.spec
Ref_Spec.spec
Default_Regex_Engine_Spec.spec