Combine builders for Vector.build and Vector.new_builder (#9922)

We have decided to keep the old new_builder, and to combine the new and old builders into one builder.
This commit is contained in:
GregoryTravis 2024-05-17 12:18:47 -04:00 committed by GitHub
parent 5c9ee94812
commit 4d49b00375
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
26 changed files with 236 additions and 351 deletions

View File

@ -147,40 +147,7 @@ type Vector a
fill length item =
Vector.new length _->item
## PRIVATE
ADVANCED
DEPRECATED `Vector.build` is the preferred way to build `Vector`s.
Creates a new vector builder instance.
A vector `Builder` is a mutable data structure, that allows for gathering
a number of elements and then converting them into a vector. This is
particularly useful when the number of elements is not known upfront.
A vector allows to store an arbitrary number of elements in linear
memory. It is the recommended data structure for most applications.
The `Vector.build` method is preferred over `.new_builder`, since it
automatically closes and returns the finished `Vector`.
Arguments:
- capacity: Initial capacity of the Vector.Builder
> Example
Construct a vector using a builder that contains the items 1 to 5.
example_new_builder =
builder = Vector.new_builder 5
do_build start stop =
builder.append start
if start >= stop then Nothing else
@Tail_Call do_build start+1 stop
do_build 1 5
builder.to_vector
new_builder : Integer -> Builder
new_builder (capacity=10) = Builder.new capacity
## PRIVATE
ADVANCED
## ADVANCED
Creates a new `Vector` by passing a `Builder` to the provided function.
A vector `Builder` is a mutable data structure, that allows for gathering
@ -274,7 +241,7 @@ type Vector a
build_multiple : Integer -> (Builder -> Any) -> Integer -> Vector Vector
build_multiple (count : Integer) (function : Builder -> Any) (initial_capacity : Integer = 10) -> Vector Vector =
if count < 0 then Error.throw (Illegal_Argument.Error "count must be non-negative: "+count.to_text) else
builders = Range.new 0 count . map (_-> Build_Style_Builder.new initial_capacity)
builders = Range.new 0 count . map (_-> Builder.new initial_capacity)
Panic.handle_wrapped_dataflow_error <|
function builders . if_not_error (builders.map .to_vector)
@ -1273,257 +1240,11 @@ type Vector a
to_list : List
to_list self = Array_Like_Helpers.to_list self
## PRIVATE
type Builder
## PRIVATE
A builder type for Enso vectors.
Arguments:
- java_builder: The accumulator for the new vector.
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.
There are two ways to create and use a `Builder`: `Vector.new_builder`
and `Vector.build`. `.build` is the preferred approach.
- `Vector.new_builder`: creates a new `Builder`, which you have to
"close" with `.to_vector` at the end to get your newly-created
`Vector`.
- `Vector.build`: takes a function which uses the `Builder`, and
automatically "closes" and returns the newly-created `Vector`.
! Error Conditions
- If an uncaught dataflow error is appended with `append`, the
dataflow error is propagated, and it is not added to the builder.
- If one or more uncaught dataflow errors are appended with
`append_vector_range`, the errors are *not* propagated. All of the
values, including dataflow errors, are added to the builder. To be
fixed in https://github.com/enso-org/enso/issues/9760.
> Example
Construct a vector using a builder that contains the items 1 to 5,
using `.new_builder`.
example_new_builder =
do_build builder start stop =
new_builder = builder.append start
if start >= stop then new_builder else
@Tail_Call do_build new_builder start+1 stop
builder = do_build Vector.new_builder 1 10
builder.to_vector
> Example
Construct a vector using a builder that contains the items 1 to 5,
using `.build`.
Vector.build initial_capacity=5 builder->
do_build start stop =
builder.append start
if start >= stop then Nothing else
@Tail_Call do_build start+1 stop
do_build 1 5
# => [1, 2, 3, 4, 5]
! TODO
We may want to revisit the fold pattern - it is required for correct
propagation of dataflow errors, but it is very easy to forget about it
and get wrong error propagation. Instead we may want to have a `Ref`
inside of the Builder. Any error detected during `append` could set
that `Ref` and then `to_vector` could propagate that error.
Value java_builder
## PRIVATE
Creates a new builder.
Arguments:
- capacity: Initial capacity of the Vector.Builder
> Example
Make a new builder
Vector.new_builder
new : Integer -> Builder
new (capacity : Integer = 10) = Builder.Value (Array_Like_Helpers.new_vector_builder capacity)
## GROUP Logical
ICON metadata
Checks if this builder is empty.
is_empty : Boolean
is_empty self = self.java_builder.isEmpty
## GROUP Logical
ICON metadata
Checks if this builder is not empty.
not_empty : Boolean
not_empty self = self.is_empty.not
## GROUP Metadata
ICON metadata
Gets the current length of the builder.
length : Integer
length self = self.java_builder.getSize
## ICON join
Appends a new element into this builder and returns it, propagating any
errors that the provided element could have contained.
Returns the builder, unless `item` is a dataflow error, in which case the
error is propagated.
Arguments:
- item: The item to append to the vector builder.
? Appending Dataflow Errors
If an uncaught dataflow error is appended with `append`, the dataflow
error is propagated, and it is not added to the builder.
> Example
Append two items.
builder = Vector.new_builder
builder . append 10 . append 20
append : Any ! Error -> Builder ! Error
append self item = case item of
_ ->
self.unsafe_append item
self
## ICON join
Appends a part of a given vector to this builder.
Arguments:
- vector: The vector from which the elements are sourced.
- start: The start index of the range to append.
- end: The end index (the first index after the last element to be
appended) of the range to be appended.
? Appending Dataflow Errors
If one or more uncaught dataflow errors are appended with
`append_vector_range`, the errors are *not* propagated. All of the
values, including dataflow errors, are added to the builder. To be
fixed in https://github.com/enso-org/enso/issues/9760.
> Example
Append a part of the vector.
builder = Vector.new_builder
builder . append_vector_range [20, 30, 40, 50] 1 3 . to_vector == [30, 40]
append_vector_range : Vector Any ! Error -> Integer -> Integer -> Builder ! Error
append_vector_range self vector (start : Integer = 0) end=vector.length =
subrange = vector.slice start end
## This workaround is needed because
`self.java_builder.addAll subrange.to_array` fails with
`Unsupported argument types: [Array]`.
append_result = self.java_builder.appendTo subrange
append_result.if_not_error self
## PRIVATE
Appends a new element into this builder.
? Propagating Dataflow Errors
Since this is an imperative operation which returns Nothing, if the
item to be appended contained a dataflow error, the operation will fail
and unless its result is inspected, the error can very easily be
ignored. To avoid this, prefer to use the `append` operation and
consume the returned builder which will contain any dataflow errors if
they need to be propagated.
Arguments:
- item: The item to append to the vector builder.
> Example
Append an item to a vector builder.
Vector.new_builder.unsafe_append 10
unsafe_append : Any -> Nothing
unsafe_append self item = self.java_builder.add item
## GROUP Selections
ICON select_row
Gets an element from the vector builder at a specified index (0-based).
Arguments:
- index: The location in the vector to get the element from. The index is
also allowed be negative, then the elements are indexed from the back
of the vector, i.e. -1 will correspond to the last element.
at : Integer -> Any ! Index_Out_Of_Bounds
at self index =
actual_index = if index < 0 then self.length + index else index
Panic.catch IndexOutOfBoundsException (self.java_builder.get actual_index) _->
Error.throw (Index_Out_Of_Bounds.Error index self.length)
## GROUP Selections
ICON select_row
Get the first element from the vector, or an `Index_Out_Of_Bounds` 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
## GROUP Selections
ICON select_row
Get the last element of the vector, or an `Index_Out_Of_Bounds` 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
## GROUP Logical
ICON preparation
Checks whether a predicate holds for at least one element of this builder.
Arguments:
- condition: A `Filter_Condition` or a function that takes a vector
element and returns a boolean value that says whether that value
satisfies a condition.
@condition Filter_Condition.default_widget
any : (Filter_Condition | (Any -> Boolean)) -> Boolean
any self (condition : Filter_Condition | (Any -> Boolean)) =
predicate = unify_condition_or_predicate condition
0.up_to self.length . any (idx -> (predicate (self.java_builder.get idx)))
## GROUP Conversions
ICON convert
Converts this builder to a vector containing all the appended elements.
> Example
Use a builder to add elements to and then create a vector.
example_to_vector =
bldr = Vector.new_builder
bldr.append 1
bldr.append 10
bldr.append 100
bldr.to_vector
to_vector : Vector Any
to_vector self =
## This creates a fresh copy of the builders storage, so any future
changes to the builder will not affect the returned vector.
Vector.from_polyglot_array self.java_builder.toArray
## PRIVATE
type Build_Style_Builder
## PRIVATE
A builder type for Enso vectors.
`Build_Style_Builder` is for use with `Vector.build`, rather than the
deprecated `Vector.new_builder`.
Arguments:
- elements_java_builder: The accumulator for the new vector.
- warnings_java_builder: The accumulator for `Warning`s that were
@ -1533,6 +1254,14 @@ type Build_Style_Builder
number of elements and then convert them to a vector. This is
particularly useful when the number of elements is not known upfront.
There are two ways to create and use a `Builder`: `Builder.new`
and `Vector.build`. `.build` is the preferred approach.
- `Builder.new`: creates a new `Builder`, which you have to
"close" with `.to_vector` at the end to get your newly-created
`Vector`.
- `Vector.build`: takes a function which uses the `Builder`, and
automatically "closes" and returns the newly-created `Vector`.
! Error Conditions
- If an uncaught dataflow error is appended with `append` or
@ -1559,25 +1288,59 @@ type Build_Style_Builder
private Value elements_java_builder warnings_java_builder
## PRIVATE
Creates a new builder.
ADVANCED
Creates a new vector builder instance.
`Vector.build` is the preferred way to build `Vector`s.
A vector `Builder` is a mutable data structure, that allows for gathering
a number of elements and then converting them into a vector. This is
particularly useful when the number of elements is not known upfront.
A vector allows to store an arbitrary number of elements in linear
memory. It is the recommended data structure for most applications.
The `Vector.build` method is preferred over direct use of `Builder.new`,
since it automatically closes and returns the finished `Vector`. The
`Builder.new` approach requires the caller to explicitly call `to_vector`
at the end, which can be more flexible within imperative code.
Arguments:
- capacity: Initial capacity of the Vector.Builder
new : Integer -> Build_Style_Builder
new (capacity : Integer = 10) -> Build_Style_Builder = Build_Style_Builder.Value (Array_Like_Helpers.new_vector_builder capacity) (Array_Like_Helpers.new_vector_builder 0)
> Example
Construct a vector using a builder that contains the items 1 to 5.
builder = Builder.new 5
do_build start stop =
builder.append start
if start >= stop then Nothing else
@Tail_Call do_build start+1 stop
do_build 1 5
builder.to_vector
# => [1, 2, 3, 4]
new : Integer -> Builder
new (capacity : Integer = 10) -> Builder = Builder.Value (Array_Like_Helpers.new_vector_builder capacity) (Array_Like_Helpers.new_vector_builder 0)
## ICON join
Appends a new element into this builder, propagating any
errors that the provided element could have contained.
Appends a new element into this builder.
Arguments:
- item: The item to append to the vector builder.
? Appending Dataflow Errors
If the value to be appended is an uncaught dataflow error, it is thrown
by the containing invocation of `Vector.build`. The error is not added
to the builder.
If a dataflow error is added to the builder, the result depends on
whether the `Builder` is being used from `.build` or created directly
with `new`.
- When using `.build`: The dataflow error is re-thrown by the containing
invocation of `Vector.build`. The error is not added to the builder.
- When using `Builder.new` directly : The dataflow error is wrapped in
a `Wrapped_Dataflow_Error` and thrown as a `Panic`. The error is not
added to the builder.
> Example
Append three items.
@ -1607,9 +1370,16 @@ type Build_Style_Builder
? Appending Dataflow Errors
If any of the values to be appended are uncaught dataflow errors, the
first one is thrown by the containing invocation of Vector.build`. No
values are added to the builder.
If a dataflow error is added to the builder, the result depends on
whether the `Builder` is being used from `.build` or created directly
with `new`.
- When using `.build`: The dataflow error is re-thrown by the containing
invocation of `Vector.build`. The error is not added to the builder.
- When using `Builder.new` directly : The dataflow error is wrapped in
a `Wrapped_Dataflow_Error` and thrown as a `Panic`. The error is not
added to the builder.
> Example
Append a vector.
@ -1705,6 +1475,32 @@ type Build_Style_Builder
length : Integer
length self = self.elements_java_builder.getSize
## GROUP Logical
ICON metadata
Checks if this builder is empty.
is_empty : Boolean
is_empty self = self.elements_java_builder.isEmpty
## GROUP Logical
ICON metadata
Checks if this builder is not empty.
not_empty : Boolean
not_empty self = self.is_empty.not
## GROUP Logical
ICON preparation
Checks whether a predicate holds for at least one element of this builder.
Arguments:
- condition: A `Filter_Condition` or a function that takes a vector
element and returns a boolean value that says whether that value
satisfies a condition.
@condition Filter_Condition.default_widget
any : (Filter_Condition | (Any -> Boolean)) -> Boolean
any self (condition : Filter_Condition | (Any -> Boolean)) =
predicate = unify_condition_or_predicate condition
0.up_to self.length . any (idx -> (predicate (self.java_builder.get idx)))
to_vector : Vector Any
to_vector self =
## This creates a fresh copy of the builders storage, so any future

View File

@ -1,7 +1,7 @@
import project.Data.Numbers.Integer
import project.Data.Text.Text
import project.Data.Time.Errors.Date_Time_Format_Parse_Error
import project.Data.Vector.Build_Style_Builder
import project.Data.Vector.Builder
import project.Data.Vector.Vector
import project.Error.Error
import project.Errors.Illegal_State.Illegal_State
@ -46,10 +46,10 @@ type Tokenizer
recursion of variables defined inside of a method is not supported in
Enso. So to achieve the mutual recursion, we instead define these as
member methods.
Instance (original_text : Text) (chars : Vector Text) (tokens_builder : Build_Style_Builder Format_Token) (optional_nesting : Ref Integer)
Instance (original_text : Text) (chars : Vector Text) (tokens_builder : Builder Format_Token) (optional_nesting : Ref Integer)
## PRIVATE
new : Build_Style_Builder -> Text -> Tokenizer
new : Builder -> Text -> Tokenizer
new builder text =
# Nothing is appended at the and as a guard to avoid checking for length.
Tokenizer.Instance text text.characters+[Nothing] builder (Ref.new 0)

View File

@ -2,6 +2,7 @@ from Standard.Base import all
import Standard.Base.Data.Array_Proxy.Array_Proxy
import Standard.Base.Data.Filter_Condition as Filter_Condition_Module
import Standard.Base.Data.Time.Errors.Date_Time_Format_Parse_Error
import Standard.Base.Data.Vector.Builder
import Standard.Base.Errors.Common.Additional_Warnings
import Standard.Base.Errors.Common.Incomparable_Values
import Standard.Base.Errors.Common.Index_Out_Of_Bounds
@ -2560,7 +2561,7 @@ type DB_Table
materialized_table = self.connection.read_statement sql column_type_suggestions . catch SQL_Error sql_error->
Error.throw (self.connection.dialect.get_error_mapper.transform_custom_errors sql_error)
warnings_builder = Vector.new_builder
warnings_builder = Builder.new
expected_types = self.columns.map .value_type
actual_types = materialized_table.columns.map .value_type
expected_types.zip actual_types expected_type-> actual_type->

View File

@ -1,5 +1,5 @@
from Standard.Base import all
from Standard.Base.Data.Vector import Build_Style_Builder
from Standard.Base.Data.Vector import Builder
from project.Errors import SQL_Warning
@ -26,7 +26,7 @@ extract_warnings jdbc_object =
builder.
This works with any object that has a `getWarnings` method, returning a `SQLWarning`.
extract_warnings_into_builder : Build_Style_Builder -> Any -> Nothing
extract_warnings_into_builder : Builder -> Any -> Nothing
extract_warnings_into_builder builder jdbc_object =
go current_warning =
if current_warning.is_nothing then Nothing else

View File

@ -1,4 +1,5 @@
from Standard.Base import all
import Standard.Base.Data.Vector.Builder
import Standard.Base.Errors.Common.Index_Out_Of_Bounds
import Standard.Base.Errors.Common.Type_Error
import Standard.Base.Errors.Illegal_Argument.Illegal_Argument
@ -100,7 +101,7 @@ create_table_from_objects (value : Convertible_To_Rows) (fields : Vector | Nothi
Map.from_vector (fields.map field_name-> [field_name, Java_Exports.make_inferred_builder len java_problem_aggregator]) error_on_duplicates=False
# This is used to ensure that field names in the resulting table are in the order they were encountered.
discovered_field_names = Vector.new_builder
discovered_field_names = Builder.new
builder_map = case preset_fields of
# Just get the queried keys from each object.

View File

@ -1,4 +1,5 @@
from Standard.Base import all
import Standard.Base.Data.Vector.Builder
import Standard.Base.Runtime.Ref.Ref
import project.Column.Column
@ -142,7 +143,7 @@ fan_out_to_rows_and_columns_fixed input_storage function at_least_one_row:Boolea
output_column_builders = Vector.new num_output_columns _-> column_builder num_input_rows
# Accumulates repeated position indices for the order mask.
order_mask_positions = Vector.new_builder num_input_rows
order_mask_positions = Builder.new num_input_rows
empty_row = [Vector.fill num_output_columns Nothing]
maybe_add_empty_row vecs = if vecs.is_empty && at_least_one_row then empty_row else vecs
@ -169,7 +170,7 @@ fan_out_to_rows_and_columns_dynamic : Any -> (Any -> Vector (Vector Any)) -> Boo
fan_out_to_rows_and_columns_dynamic input_storage function at_least_one_row column_names_for_row column_builder problem_builder =
# Accumulates the outputs of the function.
column_map = Ref.new Map.empty
output_column_builders = Vector.new_builder
output_column_builders = Builder.new
# Guess that most of the time, we'll get at least one value for each input.
num_input_rows = input_storage.size
@ -182,7 +183,7 @@ fan_out_to_rows_and_columns_dynamic input_storage function at_least_one_row colu
output_column_builders.append builder
# Accumulates repeated position indices for the order mask.
order_mask_positions = Vector.new_builder num_input_rows
order_mask_positions = Builder.new num_input_rows
maybe_add_empty_row vecs = if (vecs.is_empty && at_least_one_row).not then vecs else
[Vector.fill output_column_builders.length Nothing]
@ -244,7 +245,7 @@ map_columns_to_multiple input_column function column_count column_builder=make_s
builders = case column_count of
Nothing ->
builders = Vector.new_builder
builders = Builder.new
0.up_to num_rows . each i->
input_value = input_storage.getItemBoxed i

View File

@ -1,4 +1,5 @@
from Standard.Base import all
import Standard.Base.Data.Vector.Builder
import Standard.Base.Data.Vector.No_Wrap
import Standard.Base.Errors.Common.Index_Out_Of_Bounds
import Standard.Base.Errors.Illegal_State.Illegal_State
@ -23,7 +24,7 @@ type Join_Condition_Resolver
which can be used to deduplicate them.
resolve : Join_Condition | Text | Vector (Join_Condition | Text) -> Problem_Behavior -> Join_Condition_Resolution
resolve self conditions on_problems =
redundant_names = Vector.new_builder
redundant_names = Builder.new
left_problem_builder = Problem_Builder.new missing_input_columns_location="the left table" types_to_always_throw=[Missing_Input_Columns]
right_problem_builder = Problem_Builder.new missing_input_columns_location="the right table" types_to_always_throw=[Missing_Input_Columns]

View File

@ -1,4 +1,5 @@
from Standard.Base import all
import Standard.Base.Data.Vector.Builder
import Standard.Base.Data.Vector.No_Wrap
import Standard.Base.Errors.Illegal_Argument.Illegal_Argument
@ -47,7 +48,7 @@ prepare_columns_for_lookup base_table lookup_table key_columns_selector add_new_
lookup_table_key_columns = lookup_table.select_columns key_columns . catch Missing_Input_Columns error->
Error.throw (Missing_Input_Columns.Error error.criteria "the lookup table")
problems_to_add = Vector.new_builder
problems_to_add = Builder.new
key_columns.if_not_error <| lookup_table_key_columns.if_not_error <|
key_set = Set.from_vector key_columns
my_updated_columns = base_table.columns.map on_problems=No_Wrap base_column->

View File

@ -1,4 +1,5 @@
from Standard.Base import all
import Standard.Base.Data.Vector.Builder
import Standard.Base.Runtime.Ref.Ref
import project.Internal.Vector_Builder.Vector_Builder
@ -101,7 +102,7 @@ type Problem_Builder
new : Vector -> Boolean -> Text | Nothing -> Problem_Builder
new types_to_always_throw=[] error_on_missing_columns=False missing_input_columns_location=Nothing =
additional_types_to_throw = if error_on_missing_columns then [Missing_Input_Columns, Invalid_Aggregate_Column] else []
Problem_Builder.Value types_to_always_throw+additional_types_to_throw (Ref.new Vector_Builder.empty) (Ref.new Vector_Builder.empty) missing_input_columns_location other=Vector.new_builder
Problem_Builder.Value types_to_always_throw+additional_types_to_throw (Ref.new Vector_Builder.empty) (Ref.new Vector_Builder.empty) missing_input_columns_location other=Builder.new
## PRIVATE
Appends a `Vector` to a `Vector_Builder` stored in a `Ref`.

View File

@ -1,6 +1,7 @@
private
from Standard.Base import all
import Standard.Base.Data.Vector.Builder
import Standard.Base.Runtime.Ref.Ref
import project.Spec.Spec
@ -12,7 +13,7 @@ type Group_Builder
Arguments:
- teardown_ref: A reference to a teardown method.
Impl (builder = Vector.new_builder) (teardown_ref = Ref.new (_ -> Nothing))
Impl (builder = Builder.new) (teardown_ref = Ref.new (_ -> Nothing))
## Specifies a single test.

View File

@ -1,5 +1,6 @@
from Standard.Base import all
import Standard.Base.Data.Vector.Builder
import Standard.Base.Errors.Illegal_Argument.Illegal_Argument
import Standard.Base.Runtime.State
from Standard.Base.Runtime import assert
@ -84,7 +85,7 @@ type Suite
False ->
Test_Reporter.Ignore_Progress_Reporter
all_results_bldr = Vector.new_builder
all_results_bldr = Builder.new
junit_sb_builder = if config.should_output_junit then StringBuilder.new else Nothing
Test_Reporter.wrap_junit_testsuites config junit_sb_builder <|
matching_specs.each p->

View File

@ -1,4 +1,5 @@
from Standard.Base import all
import Standard.Base.Data.Vector.Builder
from Standard.Base.Errors.Common import Uninitialized_State
from Standard.Base.Runtime import State
@ -19,7 +20,7 @@ type Test
## Construct a Test Suite object
build : (Suite_Builder -> Any) -> Suite
build fn =
b = Vector.new_builder
b = Builder.new
fn (Suite_Builder.Impl b)
groups_vec = b.to_vector
Suite.Impl groups_vec

View File

@ -68,9 +68,9 @@ make_json_for_vector vector max_rows =
truncated = vector.take max_rows
some_values = truncated.any (v->v.is_nothing.not)
if some_values.not then JS_Object.from_pairs [["type", "Vector"], all_rows, ["json", truncated.map make_json_for_value]] else
matrix = make_json_for_matrix (Vector.new_builder truncated.length) truncated
matrix = make_json_for_matrix (Builder.new truncated.length) truncated
if matrix.is_nothing.not then JS_Object.from_pairs [["type", "Matrix"], all_rows, ["json", matrix], ["column_count", matrix.fold 0 c->v-> if v.is_nothing then c else c.max v.length]] else
object_matrix = make_json_for_object_matrix (Vector.new_builder truncated.length) truncated
object_matrix = make_json_for_object_matrix (Builder.new truncated.length) truncated
if object_matrix.is_nothing.not then JS_Object.from_pairs [["type", "Object_Matrix"], all_rows, ["json", object_matrix]] else
JS_Object.from_pairs [["type", "Vector"], all_rows, ["json", truncated.map make_json_for_value]]
@ -85,8 +85,8 @@ make_json_for_matrix current vector idx=0 = if idx == vector.length then current
_ : Array -> row.to_vector.take max_columns . map make_json_for_value
_ -> False
if to_append == False then Nothing else
next = current.append to_append
@Tail_Call make_json_for_matrix next vector idx+1
current.append to_append
@Tail_Call make_json_for_matrix current vector idx+1
## PRIVATE
Render Vector of Objects to JSON
@ -113,8 +113,8 @@ make_json_for_object_matrix current vector idx=0 = if idx == vector.length then
pairs = js_object.field_names.map f-> [f, make_json_for_value (js_object.get f)]
JS_Object.from_pairs pairs
if to_append == False then Nothing else
next = current.append to_append
@Tail_Call make_json_for_object_matrix next vector idx+1
current.append to_append
@Tail_Call make_json_for_object_matrix current vector idx+1
## PRIVATE
Render Map to JSON

View File

@ -51,7 +51,7 @@ public class ImportStandardLibrariesBenchmark {
"True",
"False",
"Vector",
"Vector.new_builder",
"Vector.build",
// from Table
"Table",
"Column.from_vector",

View File

@ -35,6 +35,7 @@ public class TypePatternBenchmarks {
var code =
"""
from Standard.Base import Integer, Vector, Any, Float
import Standard.Base.Data.Vector.Builder
avg arr =
sum acc i = if i == arr.length then acc else
@ -45,7 +46,7 @@ public class TypePatternBenchmarks {
avg (arr.map (pattern _))
gen_vec size value =
b = Vector.new_builder size
b = Builder.new size
b.append value
b.append value
add_more n = if n == size then b else

View File

@ -35,6 +35,7 @@ public class VectorBenchmarks {
var benchmarkName = SrcUtil.findName(params);
var code =
"""
import Standard.Base.Data.Vector.Builder
import Standard.Base.Data.Vector.Vector
import Standard.Base.Data.Array_Proxy.Array_Proxy
@ -44,7 +45,7 @@ public class VectorBenchmarks {
(sum 0 0) / arr.length
fibarr size modulo =
b = Vector.new_builder size
b = Builder.new size
b.append 1
b.append 1

View File

@ -33,13 +33,14 @@ public class BigNumberTest extends TestBase {
public void evaluation() throws Exception {
final String code =
"""
import Standard.Base.Data.Vector.Builder
from Standard.Base.Data.Vector import Vector
powers n =
go x v b = if x > n then b.to_vector else
b.append v
@Tail_Call go x+1 v*3 b
go 1 1 Vector.new_builder
go 1 1 Builder.new
""";
var powers = evalCode(code, "powers");
@ -89,6 +90,7 @@ public class BigNumberTest extends TestBase {
public void averageOfMixedArrayOverNumber() throws Exception {
var code =
"""
import Standard.Base.Data.Vector.Builder
from Standard.Base.Data.Vector import Vector
polyglot java import org.enso.example.TestClass
@ -96,7 +98,7 @@ public class BigNumberTest extends TestBase {
go x v b = if x > n then b.to_vector else
b.append v
@Tail_Call go x+1 v*2 b
go 1 1 Vector.new_builder
go 1 1 Builder.new
avg n = TestClass.numberArrayAverage (powers n)
""";
@ -113,6 +115,7 @@ public class BigNumberTest extends TestBase {
public void averageOfMixedArrayOverBigInteger() throws Exception {
var code =
"""
import Standard.Base.Data.Vector.Builder
from Standard.Base.Data.Vector import Vector
import Standard.Base.Data.Numbers
polyglot java import org.enso.example.TestClass
@ -121,7 +124,7 @@ public class BigNumberTest extends TestBase {
go x v b = if x > n then b.to_vector else
b.append v
@Tail_Call go x+1 v*2 b
go 1 1 Vector.new_builder
go 1 1 Builder.new
avg n = TestClass.exactArrayAverage (powers n)
""";

View File

@ -249,10 +249,19 @@ public class DebuggingEnsoTest {
Value fooFunc =
createEnsoMethod(
"""
from Standard.Base import Vector
import Standard.Base.Internal.Array_Like_Helpers
from Standard.Base import Any
from Standard.Base import Integer
new_vector_builder : Integer -> Any
new_vector_builder capacity = @Builtin_Method "Array_Like_Helpers.new_vector_builder"
type Builder
Value java_builder
foo x =
vec_builder = Vector.new_builder
java_builder = new_vector_builder 1
builder = Builder.Value java_builder
end = 42
""",
"foo");
@ -261,7 +270,7 @@ public class DebuggingEnsoTest {
debugger.startSession(
(SuspendedEvent event) -> {
if (event.getSourceSection().getCharacters().toString().strip().equals("end = 42")) {
DebugValue vecBuilder = event.getTopStackFrame().eval("vec_builder");
DebugValue vecBuilder = event.getTopStackFrame().eval("builder");
// `java_builder` is a field of `vec_builder` atom and it is a HostObject.
// As such it should be wrapped, and considered only as an interop string.
DebugValue javaBuilder = vecBuilder.getProperty("java_builder");
@ -517,12 +526,13 @@ public class DebuggingEnsoTest {
createEnsoSource(
"""
from Standard.Base import Vector
import Standard.Base.Data.Vector.Builder
bar vec num_elems =
vec.slice 0 num_elems
foo x =
vec_builder = Vector.new_builder
vec_builder = Builder.new
vec_builder.append 1
vec_builder.append 2
vec = bar (vec_builder.to_vector) (vec_builder.to_vector.length - 1)
@ -532,7 +542,7 @@ public class DebuggingEnsoTest {
List<String> expectedLines =
List.of(
"foo x =",
"vec_builder = Vector.new_builder",
"vec_builder = Builder.new",
"vec_builder.append 1",
"vec_builder.append 2",
"vec = bar (vec_builder.to_vector) (vec_builder.to_vector.length - 1)",

View File

@ -440,9 +440,9 @@ public class EnsoParserTest {
parseTest(
"""
from_java_set java_set =
owner = Vector.new_builder
group = Vector.new_builder
others = Vector.new_builder
owner = Builder.new
group = Builder.new
others = Builder.new
""");
}

View File

@ -1,4 +1,5 @@
from Standard.Base import all
import Standard.Base.Data.Vector.Builder
import Standard.Base.Errors.Empty_Error.Empty_Error
import Standard.Base.Errors.Common.Index_Out_Of_Bounds
import Standard.Base.Errors.Common.No_Such_Method
@ -215,7 +216,7 @@ add_specs suite_builder = suite_builder.group "Range" group_builder->
vec . should_equal [1, 2, 3, 4, 5]
group_builder.specify "should allow iteration, with error propagation and early exit" <|
vec_mut = Vector.new_builder
vec_mut = Builder.new
result = 1.up_to 6 . each_propagate i->
if i >= 3 then Error.throw (Illegal_Argument.Error "dummy") else
vec_mut.append i

View File

@ -15,6 +15,7 @@ import Standard.Base.Errors.Unimplemented.Unimplemented
import Standard.Base.Runtime.Ref.Ref
import Standard.Base.Runtime.State
from Standard.Base.Data.Index_Sub_Range.Index_Sub_Range import While, By_Index, Sample, Every
from Standard.Base.Panic import Wrapped_Dataflow_Error
from Standard.Test import all
@ -1011,9 +1012,57 @@ type_spec suite_builder name alter = suite_builder.group name group_builder->
mat2.transpose . should_fail_with Illegal_Argument
add_specs suite_builder =
suite_builder.group "Vector.new_builder" group_builder->
suite_builder.group "Builder.new" group_builder->
group_builder.specify "Should be able to build a vector" <|
builder = Builder.new
builder.append 1
builder.append 2
builder.append Nothing
builder.append 3
v = builder.to_vector
v . should_equal [1, 2, Nothing, 3]
builder2 = Builder.new
v2 = builder2.to_vector
v2 . should_equal []
builder3 = Builder.new 20
builder3.append 1
v3 = builder3.to_vector
v3 . should_equal [1]
group_builder.specify "Builder should throw an uncaught dataflow error as a panic if it is appended with .append" <|
builder = Builder.new
builder.append 1
Test.expect_panic_with matcher=Wrapped_Dataflow_Error (builder.append (Error.throw (Illegal_Argument.Error "asdf")))
group_builder.specify "Builder should throw an uncaught error as a panic if it is appended with .append_vector_range" <|
builder = Builder.new
builder.append 1
Test.expect_panic_with matcher=Wrapped_Dataflow_Error (builder.append_vector_range [1, Error.throw (Illegal_Argument.Error "asdf")])
group_builder.specify "Builder should propagate warnings attached to an item added to the builder with .append" <|
builder = Builder.new
ww = Warning.attach (My_Error.Error "err") 2
builder.append 1
builder.append ww
builder.append 3
v = builder.to_vector
v . should_equal [1, 2, 3]
Warning.get_all v . map .value . should_equal [My_Error.Error "err"]
group_builder.specify "Builder should propagate warnings attached to an item added to the builder with .append_vector_range" <|
builder = Builder.new
ww = Warning.attach (My_Error.Error "err") 21
builder.append 1
builder.append_vector_range [20, ww, 22]
builder.append 3
v = builder.to_vector
v . should_equal [1, 20, 21, 22, 3]
Warning.get_all v . map .value . should_equal [My_Error.Error "err"]
group_builder.specify "empty builder.get" <|
b = Vector.new_builder
b = Builder.new
e = Panic.catch Index_Out_Of_Bounds (b.at 0) err->
err.payload
Meta.type_of e . should_equal Index_Out_Of_Bounds
@ -1021,7 +1070,7 @@ add_specs suite_builder =
e.length . should_equal 0
group_builder.specify "one number builder.get" <|
b = Vector.new_builder
b = Builder.new
b.append 32
e = Panic.catch Index_Out_Of_Bounds (b.at 1) err->
err.payload
@ -1044,6 +1093,15 @@ add_specs suite_builder =
v = Vector.collect l .x .xs limit=30 stop_at=(_==List.Nil)
v . should_equal [1, 2, 3]
group_builder.specify "example" <|
builder = Builder.new 5
do_build start stop =
builder.append start
if start >= stop then Nothing else
@Tail_Call do_build start+1 stop
do_build 1 5
builder.to_vector . should_equal [1, 2, 3, 4, 5]
suite_builder.group "Vector.build" group_builder->
group_builder.specify "Should be able to build a vector" <|
v = Vector.build builder->
@ -1061,14 +1119,14 @@ add_specs suite_builder =
builder.append 1
v3 . should_equal [1]
group_builder.specify "Should propagate uncaught dataflow errors returned from build callback" <|
group_builder.specify "Should rethrow uncaught dataflow errors returned from build callback" <|
v = Vector.build builder->
builder.append 1
builder.append 2
Error.throw (Illegal_Argument.Error "asdf")
v . should_fail_with (Illegal_Argument.Error "asdf")
group_builder.specify "Builder should propagate an uncaught dataflow error if it is appended with .append" <|
group_builder.specify "Builder should rethrow an uncaught dataflow error if it is appended with .append" <|
v = Vector.build builder->
builder.append 1
builder.append (Error.throw (Illegal_Argument.Error "asdf"))
@ -1076,7 +1134,7 @@ add_specs suite_builder =
Test.fail "should not reach here because builder is immediately interrupted on error"
v . should_fail_with (Illegal_Argument.Error "asdf")
group_builder.specify "Builder should propagate an uncaught error if it is appended with .append_vector_range" <|
group_builder.specify "Builder should rethrow an uncaught error if it is appended with .append_vector_range" <|
v = Vector.build builder->
builder.append 1
builder.append_vector_range [1, Error.throw (Illegal_Argument.Error "asdf")]

View File

@ -1,4 +1,5 @@
from Standard.Base import all
import Standard.Base.Data.Vector.Builder
import Standard.Base.Errors.Illegal_State.Illegal_State
import Standard.Base.Runtime.Managed_Resource.Managed_Resource
@ -7,14 +8,14 @@ from Standard.Test import all
add_specs suite_builder = suite_builder.group "Managed_Resource" group_builder->
group_builder.specify "should call the destructor even if the action fails" <|
log_1 = Vector.new_builder
log_1 = Builder.new
r_1 = Managed_Resource.bracket 42 log_1.append x->
log_1.append x+1
x
r_1 . should_equal 42
log_1.to_vector . should_equal [43, 42]
log_2 = Vector.new_builder
log_2 = Builder.new
r_2 = Panic.recover Any <| Managed_Resource.bracket 42 log_2.append x->
log_2.append x+1
Panic.throw (Illegal_State.Error "foo")
@ -22,7 +23,7 @@ add_specs suite_builder = suite_builder.group "Managed_Resource" group_builder->
r_2.catch . should_equal (Illegal_State.Error "foo")
log_2.to_vector . should_equal [43, 42]
log_3 = Vector.new_builder
log_3 = Builder.new
r_3 = Managed_Resource.bracket 42 log_3.append x->
log_3.append x+1
r = Error.throw (Illegal_State.Error "foo")
@ -32,14 +33,14 @@ add_specs suite_builder = suite_builder.group "Managed_Resource" group_builder->
log_3.to_vector . should_equal [43, 44, 42]
group_builder.specify "should not proceed further if initialization fails" <|
log_1 = Vector.new_builder
log_1 = Builder.new
r_1 = Panic.recover Any <| Managed_Resource.bracket (Panic.throw (Illegal_State.Error "foo")) (_ -> log_1.append "destructor") _->
log_1.append "action"
42
r_1.catch . should_equal (Illegal_State.Error "foo")
log_1.to_vector . should_equal []
log_2 = Vector.new_builder
log_2 = Builder.new
r_2 = Managed_Resource.bracket (Error.throw (Illegal_State.Error "foo")) (_ -> log_2.append "destructor") _->
log_2.append "action"
42

View File

@ -1,4 +1,5 @@
from Standard.Base import all
import Standard.Base.Data.Vector.Builder
import Standard.Base.Errors.Common.Unsupported_Argument_Types
import Standard.Base.Errors.Common.Type_Error
import Standard.Base.Errors.Illegal_Argument.Illegal_Argument
@ -120,7 +121,7 @@ add_specs suite_builder =
arr.length>=1 . should_be_true
arr.first.name . should_equal "Error_Spec.throw_a_bar"
arr.first.source_location.file.name . should_equal "Error_Spec.enso"
arr.first.source_location.start_line . should_equal 36
arr.first.source_location.start_line . should_equal 37
group_builder.specify "should allow to inspect the stack trace of a recovered panic" <|
error = Panic.recover Any <| throw_a_bar_panicking
@ -349,7 +350,7 @@ add_specs suite_builder =
ref3.get . should_equal "finalized"
group_builder.specify "should propagate any panics raised in `with_finalizer` finalization" <|
v1 = Vector.new_builder
v1 = Builder.new
c1 = Panic.catch Any handler=(.payload) <|
do_finalize =
v1.append 2
@ -361,7 +362,7 @@ add_specs suite_builder =
c1 . should_equal "finalizer"
v1.to_vector . should_equal [1, 2]
v2 = Vector.new_builder
v2 = Builder.new
c2 = Panic.catch Any handler=(.payload) <|
do_finalize =
v2.append 2

View File

@ -1,4 +1,5 @@
from Standard.Base import all
import Standard.Base.Data.Vector.Builder
from Standard.Test import all
fib n b=1 = if n <= 1 then b else
@ -17,7 +18,7 @@ add_specs suite_builder =
a_plus_b_uuid = "00000000-aaaa-bbbb-0000-000000000000" # UUID for a+b
group_builder.specify "collect and filter on return updates" <|
b = Vector.new_builder
b = Builder.new
collect uuid:Text result =
if uuid == a_plus_b_uuid then
@ -46,7 +47,7 @@ add_specs suite_builder =
b.to_vector.length . should_equal 1
group_builder.specify "access local variables " <|
b = Vector.new_builder
b = Builder.new
collect uuid:Text ~result =
if uuid == a_plus_b_uuid then
@ -101,7 +102,7 @@ add_specs suite_builder =
group_builder.specify "call and collect on return updates" <|
n1_plus_n2 = "00000000-eeee-bbbb-2222-000000000000" # UUID for n1+n2
b = Vector.new_builder
b = Builder.new
call_fn uuid:Text fn:Function (args : Vector Any) =
fn.to_text . should_contain "Integer.+"
@ -189,7 +190,7 @@ add_specs suite_builder =
group_builder.specify "Access (even default) arguments of calls" <|
b = Vector.new_builder
b = Builder.new
call_fn uuid:Text fn:Function args:Any =
if uuid == "00000000-ffff-1111-bbbb-000000000000" then
@ -263,5 +264,5 @@ main filter=Nothing =
#### METADATA ####
[[{"index":{"value":131},"size":{"value":3}},"00000000-aaaa-bbbb-0000-000000000000"],[{"index":{"value":73},"size":{"value":61}},"00000000-ffff-bbbb-0000-000000000000"],[{"index":{"value":226},"size":{"value":5}},"00000000-eeee-bbbb-2222-000000000000"],[{"index":{"value":119},"size":{"value":7}},"00000000-ffff-1111-bbbb-000000000000"]]
[[{"index":{"value":172},"size":{"value":3}},"00000000-aaaa-bbbb-0000-000000000000"],[{"index":{"value":114},"size":{"value":61}},"00000000-ffff-bbbb-0000-000000000000"],[{"index":{"value":267},"size":{"value":5}},"00000000-eeee-bbbb-2222-000000000000"],[{"index":{"value":160},"size":{"value":7}},"00000000-ffff-1111-bbbb-000000000000"]]

View File

@ -1,4 +1,5 @@
from Standard.Base import all
import Standard.Base.Data.Vector.Builder
import Standard.Base.Errors.Encoding_Error.Encoding_Error
polyglot java import java.nio.CharBuffer
@ -29,7 +30,7 @@ add_specs suite_builder =
fragment = 'Hello 😎🚀🚧!'
contents = 1.up_to 1000 . map _->fragment . join '\n'
contents.write f . should_succeed
all_codepoints = Vector.new_builder
all_codepoints = Builder.new
read_chars decoder n =
case read_characters decoder n of
Nothing -> Nothing

View File

@ -1,4 +1,6 @@
from Standard.Base import all
import Standard.Base.Data.Vector.Builder
from Standard.Test import all
import project.Helpers.Table_Aggregate_Auto_Constructor
@ -6,7 +8,7 @@ import project.Helpers.Table_Aggregate_Auto_Constructor
add_specs suite_builder =
suite_builder.group "Autoconstructor Instrumentation" group_builder->
group_builder.specify "compare ..Count and Aggregate_Column.Count" <|
lines_builder = Vector.new_builder
lines_builder = Builder.new
pair = Table_Aggregate_Auto_Constructor.perform lines_builder.append