builtin(list): add List.chunksOf

This commit is contained in:
Elias Mulhall 2023-10-07 11:54:34 -04:00
parent f966afc23e
commit b7923ac542
3 changed files with 54 additions and 0 deletions

View file

@ -67,6 +67,7 @@ interface List
releaseExcessCapacity, releaseExcessCapacity,
walkBackwardsUntil, walkBackwardsUntil,
countIf, countIf,
chunksOf,
] ]
imports [ imports [
Bool.{ Bool, Eq }, Bool.{ Bool, Eq },
@ -1197,6 +1198,26 @@ splitLast = \list, delimiter ->
Err NotFound -> Err NotFound Err NotFound -> Err NotFound
## Splits the list into many chunks, each of which is length of the given chunk
## size. The last chunk will be shorter if the list does not evenly divide by the
## chunk size. If the provided list is empty or if the chunk size is 0 then the
## result is an empty list.
chunksOf : List a, Nat -> List (List a)
chunksOf = \list, chunkSize ->
if chunkSize == 0 || List.isEmpty list then
[]
else
chunkCapacity = Num.divCeil (List.len list) chunkSize
chunksOfHelp list chunkSize (List.withCapacity chunkCapacity)
chunksOfHelp : List a, Nat, List (List a) -> List (List a)
chunksOfHelp = \listRest, chunkSize, chunks ->
if List.isEmpty listRest then
chunks
else
{ before, others } = List.split listRest chunkSize
chunksOfHelp others chunkSize (List.append chunks before)
## Like [List.map], except the transformation function returns a [Result]. ## Like [List.map], except the transformation function returns a [Result].
## If that function ever returns `Err`, [mapTry] immediately returns that `Err`. ## If that function ever returns `Err`, [mapTry] immediately returns that `Err`.
## If it returns `Ok` for every element, [mapTry] returns `Ok` with the transformed list. ## If it returns `Ok` for every element, [mapTry] returns `Ok` with the transformed list.

View file

@ -1432,6 +1432,7 @@ define_builtins! {
81 LIST_RELEASE_EXCESS_CAPACITY: "releaseExcessCapacity" 81 LIST_RELEASE_EXCESS_CAPACITY: "releaseExcessCapacity"
82 LIST_UPDATE: "update" 82 LIST_UPDATE: "update"
83 LIST_WALK_WITH_INDEX: "walkWithIndex" 83 LIST_WALK_WITH_INDEX: "walkWithIndex"
84 LIST_CHUNKS_OF: "chunksOf"
} }
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

@ -487,6 +487,38 @@ fn list_split_last() {
); );
} }
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_chunks_of() {
assert_evals_to!(
"List.chunksOf [1, 2, 3, 4, 5, 6, 7, 8] 3",
RocList::from_slice(&[
RocList::from_slice(&[1, 2, 3]),
RocList::from_slice(&[4, 5, 6]),
RocList::from_slice(&[7, 8]),
]),
RocList<RocList<i64>>
);
assert_evals_to!(
"List.chunksOf [1, 2, 3, 4] 5",
RocList::from_slice(&[RocList::from_slice(&[1, 2, 3, 4]),]),
RocList<RocList<i64>>
);
assert_evals_to!(
"List.chunksOf [1, 2, 3] 0",
RocList::from_slice(&[]),
RocList<RocList<i64>>
);
assert_evals_to!(
"List.chunksOf [] 5",
RocList::from_slice(&[]),
RocList<RocList<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_drop() { fn list_drop() {