Add List.forEachTry! builtin

This commit is contained in:
Agus Zubiaga 2024-11-09 23:13:49 -03:00
parent ce568c01c1
commit 6d0cec253d
No known key found for this signature in database
4 changed files with 80 additions and 6 deletions

View file

@ -1141,6 +1141,31 @@ mod cli_run {
);
}
#[test]
#[cfg_attr(windows, ignore)]
#[cfg_attr(target_os = "linux", ignore)]
fn effectful_for_each_try() {
test_roc_app(
"crates/cli/tests/effectful",
"for_each_try.roc",
&[],
&[],
&[],
indoc!(
r#"
0
2
4
6
8
9 is not even! ABORT!
"#
),
UseValgrind::No,
TestCliCommands::Dev,
);
}
#[test]
#[cfg_attr(windows, ignore)]
fn transitive_expects() {

View file

@ -0,0 +1,23 @@
app [main!] { pf: platform "../../../../examples/cli/effects-platform/main.roc" }
import pf.Effect
main! : {} => {}
main! = \{} ->
good = [0, 2, 4] |> List.forEachTry! validate!
expect good == Ok {}
bad = [6, 8, 9, 10] |> List.forEachTry! validate!
expect bad == Err 9
{}
validate! : U32 => Result {} U32
validate! = \x ->
if Num.isEven x then
Effect.putLine! "✅ $(Num.toStr x)"
Ok {}
else
Effect.putLine! "$(Num.toStr x) is not even! ABORT!"
Err x

View file

@ -71,6 +71,7 @@ module [
chunksOf,
concatUtf8,
forEach!,
forEachTry!,
]
import Bool exposing [Bool, Eq]
@ -1384,7 +1385,6 @@ concatUtf8 : List U8, Str -> List U8
expect (List.concatUtf8 [1, 2, 3, 4] "🐦") == [1, 2, 3, 4, 240, 159, 144, 166]
## Run an effectful function for each element on the list.
##
## ```roc
@ -1392,12 +1392,37 @@ expect (List.concatUtf8 [1, 2, 3, 4] "🐦") == [1, 2, 3, 4, 240, 159, 144, 166]
## createAccount! name
## log! "Account created"
## ```
##
## If the function might fail or you need to return early, use [forEachTry!].
forEach! : List a, (a => {}) => {}
forEach! = \l, f! ->
when l is
forEach! = \list, func! ->
when list is
[] ->
{}
[x, .. as xs] ->
f! x
forEach! xs f!
[elem, .. as rest] ->
func! elem
forEach! rest func!
## Run an effectful function that might fail for each element on the list.
##
## If the function returns `Err`, the iteration stops and the error is returned.
##
## ```roc
## List.forEachTry! filesToDelete \path ->
## try File.delete! path
## Stdout.line! "$(path) deleted"
## ```
forEachTry! : List a, (a => Result {} err) => Result {} err
forEachTry! = \list, func! ->
when list is
[] ->
Ok {}
[elem, .. as rest] ->
when func! elem is
Ok {} ->
forEachTry! rest func!
Err err ->
Err err

View file

@ -1510,6 +1510,7 @@ define_builtins! {
88 LIST_LEN_USIZE: "lenUsize"
89 LIST_CONCAT_UTF8: "concatUtf8"
90 LIST_FOR_EACH_FX: "forEach!"
91 LIST_FOR_EACH_TRY_FX: "forEachTry!"
}
7 RESULT: "Result" => {
0 RESULT_RESULT: "Result" exposed_type=true // the Result.Result type alias