Skip to content

Commit

Permalink
Docs about collectors (#256)
Browse files Browse the repository at this point in the history
Documentation for arrow-kt/arrow#3280
  • Loading branch information
serras authored Feb 27, 2024
1 parent c9fc737 commit f9534da
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 4 deletions.
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)

0 comments on commit f9534da

Please sign in to comment.