Skip to content

Commit

Permalink
feat(stdlib): Add chunk function to Array module (#1708)
Browse files Browse the repository at this point in the history
* feat: Add `Array.Chunk`

* chore: Apply suggestions from code review

* chore: Use an exception for array length 0

* chore: Remove Partial Behaviour

* chore: use optional argument on slice

* chore: Run formatter

* chore: apply changes from code review
  • Loading branch information
spotandjake committed Apr 16, 2023
1 parent 3c3c4d9 commit fba7c1d
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 0 deletions.
10 changes: 10 additions & 0 deletions compiler/test/stdlib/array.test.gr
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,16 @@ let arr9 = [>]
Array.rotate(1, arr9)
assert arr9 == [>]

// Array.chunk
assert Array.chunk(2, [>]) == [>]
assert Array.chunk(2, [> 1, 2, 3, 4]) == [> [> 1, 2], [> 3, 4]]
assert Array.chunk(2, [> 1, 2, 3, 4, 5]) == [> [> 1, 2], [> 3, 4], [> 5]]
assert Array.chunk(3, [> 1, 2, 3, 4, 5, 6, 7, 8]) ==
[> [> 1, 2, 3], [> 4, 5, 6], [> 7, 8]]
assert Array.chunk(3, [> 1, 2, 3, 4, 5, 6, 7, 8]) ==
[> [> 1, 2, 3], [> 4, 5, 6], [> 7, 8]]
assert Array.chunk(10, [> 1, 2, 3, 4, 5]) == [> [> 1, 2, 3, 4, 5]]

module Immutable {
from Array use { Immutable as Array }

Expand Down
49 changes: 49 additions & 0 deletions stdlib/array.gr
Original file line number Diff line number Diff line change
Expand Up @@ -1020,6 +1020,55 @@ provide let rotate = (n, arr) => {
}
}

let rec chunkHelp = (chunkSize, arr, arrLen, chunkStartIndex) => {
if (arrLen == 0) {
[]
} else if (arrLen < chunkSize) {
[slice(chunkStartIndex, arr)]
} else {
// create the first chunk of the given array
let firstChunk = slice(
chunkStartIndex,
end=chunkStartIndex + chunkSize,
arr
)
let restChunks = chunkHelp(
chunkSize,
arr,
arrLen - chunkSize,
chunkStartIndex + chunkSize
)
[firstChunk, ...restChunks]
}
}

/**
* Splits the given array into chunks of the provided size.
* If the array cannot be split evenly, the final chunk will contain the remaining elements.
*
* @param chunkSize: The maximum size of each chunk
* @param arr: The array to chunk
* @returns An array of chunks
*
* @throws InvalidArgument(String): When `chunkSize` is not an integer
* @throws InvalidArgument(String): When `chunkSize` is less than one
*
* @example chunk(2, [> 1, 2, 3, 4, 5]) == [> [> 1, 2], [> 3, 4], [> 5] ]
* @example chunk(2, [> 1, 2, 3, 4]) == [> [> 1, 2], [> 3, 4] ]
*
* @since v0.6.0
*/
provide let chunk = (chunkSize, arr) => {
if (chunkSize <= 0) {
throw Exception.InvalidArgument("chunkSize must be greater than 0")
} else {
checkLength(chunkSize)
let arrLen = length(arr)
let chunks = chunkHelp(chunkSize, arr, arrLen, 0)
fromList(chunks)
}
}

/**
* An immutable array implementation.
*
Expand Down
44 changes: 44 additions & 0 deletions stdlib/array.md
Original file line number Diff line number Diff line change
Expand Up @@ -1288,6 +1288,50 @@ let array = [> 1, 2, 3, 4, 5]; rotate(2, arr); arr == [> 3, 4, 5, 1, 2]
let array = [> 1, 2, 3, 4, 5]; rotate(-1, arr); arr == [> 5, 1, 2, 3, 4]
```

### Array.**chunk**

<details disabled>
<summary tabindex="-1">Added in <code>next</code></summary>
No other changes yet.
</details>

```grain
chunk : (chunkSize: Number, arr: Array<a>) -> Array<Array<a>>
```

Splits the given array into chunks of the provided size.
If the array cannot be split evenly, the final chunk will contain the remaining elements.

Parameters:

|param|type|description|
|-----|----|-----------|
|`chunkSize`|`Number`|The maximum size of each chunk|
|`arr`|`Array<a>`|The array to chunk|

Returns:

|type|description|
|----|-----------|
|`Array<Array<a>>`|An array of chunks|

Throws:

`InvalidArgument(String)`

* When `chunkSize` is not an integer
* When `chunkSize` is less than one

Examples:

```grain
chunk(2, [> 1, 2, 3, 4, 5]) == [> [> 1, 2], [> 3, 4], [> 5] ]
```

```grain
chunk(2, [> 1, 2, 3, 4]) == [> [> 1, 2], [> 3, 4] ]
```

## Array.Immutable

An immutable array implementation.
Expand Down

0 comments on commit fba7c1d

Please sign in to comment.