Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs about collectors #256

Merged
merged 2 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions content/docs/learn/collections-functions/collectors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
---
sidebar_position: 2
description: Better aggregation over sequences
---

# Collectors

Collectors help build complex computations over sequences of values,
guaranteeing that those values are consumed only once.

Take for example the computation of the average of a list. You can
certainly write a simple version using the built-in functions,

<!--- INCLUDE
val list = listOf(1, 2, 3)
-->

```kotlin
val average = list.sum() / list.size
```
<!--- KNIT example-collectors-01.kt -->

Note however that this implementation traverses the list _twice_,
one per operation over the list. This may not be a problem for small
lists but could become more problematic with longer collections.
Some data structures, like `Sequence` or `Flow`, impose an
even larger footprint, as their elements are computed every time
you need a new one.

Collectors separate the description of the aggregation you want
to perform from the actual collection. To create a new collector
you use one of the built-in ones, and combine them using `zip`.

```kotlin
import arrow.collectors.Collectors
import arrow.collectors.collect
import arrow.collectors.zip

fun divide(x: Int, y: Int): Double = x.toDouble() / y.toDouble()

val averageCollector = zip(Collectors.sum, Collectors.length, ::divide)
```

<!--- INCLUDE
val list = listOf(1, 2, 3)
-->

You then may apply the collector to the sequence or collection you want.

```kotlin
val average = list.collect(averageCollector)
```
<!--- KNIT example-collectors-02.kt -->

:::note Influences

The API implemented in `arrow-collectors` is heavily influenced by
Java's [`Collector`](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collector.html)
and Haskell's [`foldl` library](https://hackage.haskell.org/package/foldl/docs/Control-Foldl.html).

:::
2 changes: 1 addition & 1 deletion content/docs/learn/collections-functions/memoize.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 3
sidebar_position: 4
description: Avoiding duplicate work for pure functions
---

Expand Down
2 changes: 1 addition & 1 deletion content/docs/learn/collections-functions/recursive.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 2
sidebar_position: 3
description: Making functions stack-safe and efficient
---

Expand Down
2 changes: 1 addition & 1 deletion content/docs/learn/collections-functions/utils.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 4
sidebar_position: 5
description: Composition, partial application, and currying
---

Expand Down
2 changes: 1 addition & 1 deletion content/docs/learn/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Each section in the documentation roughly corresponds to one of the libraries th
| `arrow-optics` + `arrow-optics-ksp-plugin` <br /> _Companion to [data](https://kotlinlang.org/docs/data-classes.html) and [sealed](https://kotlinlang.org/docs/sealed-classes.html) classes_ | Utilities for [immutable data](../immutable-data/intro/) |
| `arrow-fx-stm` | [Software Transactional Memory](../coroutines/stm/) (STM) |
| `arrow-atomic` <br /> _Multiplatform-ready [references](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.native.concurrent/-atomic-reference/)_ | [Atomic references](../coroutines/concurrency-primitives/#atomic) |
| `arrow-collectors` <br /> _Kotlin-ready [collectors](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/stream/package-summary.html)_ | Better aggregation over sequences |
| `arrow-collectors` <br /> _Companion to [`fold`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/fold.html) and [`reduce`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/reduce.html)_ | [Aggregation with single traversal](../collections-functions/collectors/) |
| `arrow-eval` <br /> _More powerful [laziness](https://kotlinlang.org/docs/delegated-properties.html#lazy-properties)_ | [Control over evaluation](../collections-functions/eval/) |
| `arrow-functions` <br /> <small>Part of `arrow-core` in 1.x</small> | [Utilities for functions](../collections-functions/utils/) |
| `arrow-core-high-arity` | `arrow-core` for more than 10 parameters |
Expand Down
6 changes: 6 additions & 0 deletions guide/src/test/kotlin/examples/example-collectors-01.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// This file was automatically generated from collectors.md by Knit tool. Do not edit.
package arrow.website.examples.exampleCollectors01

val list = listOf(1, 2, 3)

val average = list.sum() / list.size
13 changes: 13 additions & 0 deletions guide/src/test/kotlin/examples/example-collectors-02.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// This file was automatically generated from collectors.md by Knit tool. Do not edit.
package arrow.website.examples.exampleCollectors02

import arrow.collectors.Collectors
import arrow.collectors.collect
import arrow.collectors.zip

fun divide(x: Int, y: Int): Double = x.toDouble() / y.toDouble()

val averageCollector = zip(Collectors.sum, Collectors.length, ::divide)
val list = listOf(1, 2, 3)

val average = list.collect(averageCollector)