Add builtin List.walkWithIndexUntil

This commit is contained in:
Bryce Miller 2023-12-11 23:04:40 -05:00
parent f795d0856a
commit 59eb28ef58
No known key found for this signature in database
GPG key ID: F1E97BF8DF152350
4 changed files with 46 additions and 0 deletions

View file

@ -32,6 +32,7 @@ interface List
product, product,
walkWithIndex, walkWithIndex,
walkUntil, walkUntil,
walkWithIndexUntil,
walkFrom, walkFrom,
walkFromUntil, walkFromUntil,
range, range,
@ -520,6 +521,25 @@ walkWithIndexHelp = \list, state, f, index, length ->
else else
state state
## Like [walkUntil], but at each step the function also receives the index of the current element.
walkWithIndexUntil : List elem, state, (state, elem, Nat -> [Continue state, Break state]) -> state
walkWithIndexUntil = \list, state, f ->
when walkWithIndexUntilHelp list state f 0 (List.len list) is
Continue new -> new
Break new -> new
## internal helper
walkWithIndexUntilHelp : List elem, s, (s, elem, Nat -> [Continue s, Break b]), Nat, Nat -> [Continue s, Break b]
walkWithIndexUntilHelp = \list, state, f, index, length ->
if index < length then
when f state (List.getUnsafe list index) index is
Continue nextState ->
walkWithIndexUntilHelp list nextState f (Num.addWrap index 1) length
Break b -> Break b
else
Continue state
## Note that in other languages, `walkBackwards` is sometimes called `reduceRight`, ## Note that in other languages, `walkBackwards` is sometimes called `reduceRight`,
## `fold`, `foldRight`, or `foldr`. ## `fold`, `foldRight`, or `foldr`.
walkBackwards : List elem, state, (state, elem -> state) -> state walkBackwards : List elem, state, (state, elem -> state) -> state

View file

@ -1439,6 +1439,7 @@ define_builtins! {
83 LIST_WALK_WITH_INDEX: "walkWithIndex" 83 LIST_WALK_WITH_INDEX: "walkWithIndex"
84 LIST_APPEND_IF_OK: "appendIfOk" 84 LIST_APPEND_IF_OK: "appendIfOk"
85 LIST_PREPEND_IF_OK: "prependIfOk" 85 LIST_PREPEND_IF_OK: "prependIfOk"
86 LIST_WALK_WITH_INDEX_UNTIL: "walkWithIndexUntil"
} }
7 RESULT: "Result" => { 7 RESULT: "Result" => {
0 RESULT_RESULT: "Result" exposed_type=true // the Result.Result type alias 0 RESULT_RESULT: "Result" exposed_type=true // the Result.Result type alias

View file

@ -3768,6 +3768,14 @@ mod solve_expr {
); );
} }
#[test]
fn list_walk_with_index_until() {
infer_eq_without_problem(
indoc!(r#"List.walkWithIndexUntil"#),
"List elem, state, (state, elem, Nat -> [Break state, Continue state]) -> state",
);
}
#[test] #[test]
fn list_drop_at() { fn list_drop_at() {
infer_eq_without_problem( infer_eq_without_problem(

View file

@ -990,6 +990,23 @@ fn list_walk_until_sum() {
); );
} }
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
fn list_walk_with_index_until_sum() {
assert_evals_to!(
r#"
List.walkWithIndexUntil [5, 7, 2, 3] 0 (\state, elem, index ->
if elem % 2 == 0 then
Break state
else
Continue (elem + index + state)
)
"#,
13,
i64
);
}
#[test] #[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
fn list_walk_implements_position() { fn list_walk_implements_position() {