Make errors propagate out of each (#9742)

Make errors propagate out of each
This commit is contained in:
AdRiley 2024-04-23 18:14:54 +01:00 committed by GitHub
parent 96fdb67204
commit 6f3e649e7a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 97 additions and 29 deletions

View File

@ -914,6 +914,9 @@ type Array
Unlike `map`, this method does not return the individual results,
therefore it is only useful for side-effecting computations.
If the function returns a dataflow error, the error is converted to a
panic and thrown immediately stopping further processing.
Arguments:
- function: A function to apply to each element of the array.

View File

@ -12,6 +12,7 @@ import project.Errors.Empty_Error.Empty_Error
import project.Function.Function
import project.Meta
import project.Nothing.Nothing
import project.Panic.Panic
from project.Data.Boolean import Boolean, False, True
from project.Data.Filter_Condition import unify_condition_or_predicate, unify_condition_predicate_or_element
from project.Data.List.List import Cons, Nil
@ -355,6 +356,9 @@ type List
Unlike `map`, this method does not return the individual results,
therefore it is only useful for side-effecting computations.
If the function returns a dataflow error, the error is converted to a
panic and thrown immediately stopping further processing.
> Example
Print each of the list elements to the standard output.
@ -366,10 +370,9 @@ type List
go list = case list of
Nil -> Nothing
Cons h t ->
f h
Panic.rethrow (f h)
@Tail_Call go t
go self
Nothing
## GROUP Selections
ICON order

View File

@ -366,9 +366,12 @@ type Map key value
- function: The function to apply to each value in the map, taking a
value and returning anything.
This method does not return the results, so is only useful for performing
This method does not return the results, so it is only useful for performing
computations with side-effects.
If the function returns a dataflow error, the error is converted to a
panic and thrown immediately stopping further processing.
> Example
Printing each value in the map.
@ -389,7 +392,7 @@ type Map key value
- function: The function to apply to each key-value pair in the map,
taking a key and a value and returning anything.
This method does not return the results, so is only useful for performing
This method does not return the results, so it is only useful for performing
computations with side-effects.
> Example

View File

@ -8,6 +8,7 @@ import project.Errors.Common.Index_Out_Of_Bounds
import project.Errors.Common.Not_Found
import project.Function.Function
import project.Nothing.Nothing
import project.Panic.Panic
from project.Data.Text.Extensions import all
## A pair of elements.
@ -256,6 +257,9 @@ type Pair
Unlike `map`, this method does not return the individual results,
therefore it is only useful for side-effecting computations.
If the function returns a dataflow error, the error is converted to a
panic and thrown immediately stopping further processing.
Arguments:
- function: A function to apply to each element of the pair.
@ -265,8 +269,8 @@ type Pair
Pair.new 1 2 . each IO.println
each : (Any -> Any) -> Nothing
each self f =
f self.first
f self.second
Panic.rethrow (f self.first)
Panic.rethrow (f self.second)
Nothing
## PRIVATE

View File

@ -12,6 +12,7 @@ import project.Errors.Illegal_Argument.Illegal_Argument
import project.Errors.Illegal_State.Illegal_State
import project.Function.Function
import project.Nothing.Nothing
import project.Panic.Panic
from project.Data.Boolean import Boolean, False, True
from project.Data.Filter_Condition import unify_condition_or_predicate
@ -237,6 +238,12 @@ type Range
ADVANCED
Applies a function for each element in the range.
This method does not return the results, so it is only useful for performing
computations with side-effects.
If the function returns a dataflow error, the error is converted to a
panic and thrown immediately stopping further processing.
Arguments:
- function: The function to apply to each integer in the range.
@ -249,7 +256,7 @@ type Range
end_condition = if self.step > 0 then (>=) else (<=)
go current =
if end_condition current self.end then Nothing else
function current
Panic.rethrow (function current)
@Tail_Call go current+self.step
go self.start

View File

@ -31,6 +31,7 @@ import project.Errors.Problem_Behavior.Problem_Behavior
import project.Errors.Time_Error.Time_Error
import project.Meta
import project.Nothing.Nothing
import project.Panic.Panic
from project.Data.Boolean import Boolean, False, True
from project.Data.Json import Invalid_JSON, JS_Object, Json
from project.Data.Numbers import Float, Integer, Number, Number_Parse_Error
@ -76,6 +77,12 @@ Text.reverse self =
Arguments:
- function: The operation to apply to each character in the text.
This method does not return the results, so it is only useful for performing
computations with side-effects.
If the function returns a dataflow error, the error is converted to a
panic and thrown immediately stopping further processing.
! What is a Character?
A character is defined as an Extended Grapheme Cluster, see Unicode
Standard Annex 29. This is the smallest unit that still has semantic
@ -91,7 +98,7 @@ Text.each self function =
iterator.setText self
iterate prev nxt = if nxt == -1 then Nothing else
function (Text_Utils.substring self prev nxt)
Panic.rethrow (function (Text_Utils.substring self prev nxt))
@Tail_Call iterate nxt iterator.next
iterate iterator.first iterator.next

View File

@ -299,6 +299,12 @@ type Date_Range
ADVANCED
Applies a function for each element in the range.
This method does not return the results, so it is only useful for performing
computations with side-effects.
If the function returns a dataflow error, the error is converted to a
panic and thrown immediately stopping further processing.
Arguments:
- function: The function to apply to each integer in the range.

View File

@ -764,6 +764,9 @@ type Vector a
Unlike `map`, this method does not return the individual results,
therefore it is only useful for side-effecting computations.
If the function returns a dataflow error, the error is converted to a
panic and thrown immediately stopping further processing.
Arguments:
- function: A function to apply to each element of the vector.

View File

@ -21,28 +21,29 @@ expand_column (table : Table) (column : Text | Integer) (fields : (Vector Text)
column_object = table.at column
expanded = create_table_from_objects column_object.to_vector fields
output_builder = Vector.new_builder table.column_count+expanded.column_count-1
expanded.if_not_error <|
output_builder = Vector.new_builder table.column_count+expanded.column_count-1
## Resolve names
resolved_prefix = case prefix of
Prefix_Name.None -> ""
Prefix_Name.Column_Name -> column_object.name+" "
Prefix_Name.Custom value -> value
default_name = case prefix of
Prefix_Name.None -> "Value"
Prefix_Name.Column_Name -> column_object.name
Prefix_Name.Custom value -> value
naming_strategy = table.column_naming_helper.create_unique_name_strategy
naming_strategy.mark_used (table.column_names.filter (c->c!=column_object.name))
new_names = naming_strategy.make_all_unique (expanded.column_names.map n-> if n=='Value' then default_name else resolved_prefix+n)
new_columns = new_names.zip expanded.columns (n->c-> c.rename n)
## Resolve names
resolved_prefix = case prefix of
Prefix_Name.None -> ""
Prefix_Name.Column_Name -> column_object.name+" "
Prefix_Name.Custom value -> value
default_name = case prefix of
Prefix_Name.None -> "Value"
Prefix_Name.Column_Name -> column_object.name
Prefix_Name.Custom value -> value
naming_strategy = table.column_naming_helper.create_unique_name_strategy
naming_strategy.mark_used (table.column_names.filter (c->c!=column_object.name))
new_names = naming_strategy.make_all_unique (expanded.column_names.map n-> if n=='Value' then default_name else resolved_prefix+n)
new_columns = new_names.zip expanded.columns (n->c-> c.rename n)
## Create Merged Columns
table.columns.each c->
if c.name != column_object.name then output_builder.append c else
output_builder.append_vector_range new_columns
## Create Merged Columns
table.columns.each c->
if c.name != column_object.name then output_builder.append c else
output_builder.append_vector_range new_columns
Table.new output_builder.to_vector
Table.new output_builder.to_vector
## PRIVATE
GROUP Standard.Base.Conversions

View File

@ -224,6 +224,11 @@ add_specs suite_builder = suite_builder.group "List" group_builder->
State.put Number s+el
State.get Number
sum.should_equal 6
group_builder.specify "dataflow errors in .each should become panics" <|
do_write x =
Error.throw "Failed to write "+x.to_text
Test.expect_panic_with (l.each do_write) Text
group_builder.specify "should allow reversing with .reverse" <|
l.reverse.first.should_equal 3

View File

@ -100,6 +100,11 @@ type_spec suite_builder name ctor = suite_builder.group name group_builder->
ctor 10 20 . each vec_mut.append
vec_mut.to_vector . should_equal [10, 20]
group_builder.specify "dataflow errors in .each should become panics" <|
do_write x =
Error.throw "Failed to write "+x.to_text
Test.expect_panic_with (ctor 10 20 . each do_write) Text
add_specs suite_builder =
suite_builder.group "Pair " group_builder->
group_builder.specify "should be created by new" <|

View File

@ -896,6 +896,11 @@ add_specs suite_builder =
'a'.each builder2.append
builder2.to_vector . should_equal ['a']
group_builder.specify "dataflow errors in .each should become panics" <|
do_write x =
Error.throw "Failed to write "+x.to_text
Test.expect_panic_with ("abc".each do_write) Text
group_builder.specify "should check for contains using Unicode normalization" <|
"Hello".contains "ell" . should_be_true
"Hello".contains "eLl" . should_be_false

View File

@ -423,6 +423,12 @@ type_spec suite_builder name alter = suite_builder.group name group_builder->
result = Vector.build builder->
vec.each builder.append
result . should_equal vec
group_builder.specify "dataflow errors in .each should become panics" <|
do_write x =
Error.throw "Failed to write "+x.to_text
vec = alter [1, 2, 3, 4]
Test.expect_panic_with (vec.each do_write) Text
group_builder.specify "should accept changed elements" <|
vec = alter <| Vector.build builder->

View File

@ -163,6 +163,10 @@ add_specs suite_builder =
(rethrown_panic.stack_trace.length > 0).should_be_true
(rethrown_panic.stack_trace.map .name) . should_equal (caught_panic.stack_trace.map .name)
group_builder.specify "panic.rethrow" <|
result = (Error.throw 42)
Test.expect_panic_with (Panic.rethrow result) Integer
group_builder.specify "should allow the pattern for handling selected exceptions" <|
perform_operation ~action =
Panic.catch Any action caught_panic->

View File

@ -159,7 +159,10 @@ add_specs suite_builder setup =
False ->
a.date_part Time_Period.Nanosecond . should_fail_with Unsupported_Database_Operation
[a.date_part Time_Period.Second, a.date_part Time_Period.Millisecond, a.date_part Time_Period.Microsecond, a.date_part Time_Period.Nanosecond].each c->
testCases = [a.date_part Time_Period.Second, a.date_part Time_Period.Millisecond, a.date_part Time_Period.Microsecond]
if setup.test_selection.supports_nanoseconds_in_time then
testCases = testCases + (a.date_part Time_Period.Nanosecond)
testCases.each c->
Test.with_clue "The column "+c.name+" value type ("+c.value_type.to_display_text+") should be an integer: " <|
c.value_type.is_integer.should_be_true
@ -184,7 +187,10 @@ add_specs suite_builder setup =
False ->
a.date_part Time_Period.Nanosecond . should_fail_with Unsupported_Database_Operation
[a.date_part Date_Period.Quarter, a.date_part Date_Period.Week, a.date_part Time_Period.Second, a.date_part Time_Period.Millisecond, a.date_part Time_Period.Microsecond, a.date_part Time_Period.Nanosecond].each c->
testCases = [a.date_part Date_Period.Quarter, a.date_part Date_Period.Week, a.date_part Time_Period.Second, a.date_part Time_Period.Millisecond, a.date_part Time_Period.Microsecond]
if setup.test_selection.supports_nanoseconds_in_time then
testCases = testCases + (a.date_part Time_Period.Nanosecond)
testCases.each c->
Test.with_clue "The column "+c.name+" value type ("+c.value_type.to_display_text+") should be an integer: " <|
c.value_type.is_integer.should_be_true