feat: add docs on array fold

This commit is contained in:
Fernando Araoz 2024-11-07 16:02:52 -05:00
parent 1783097ba9
commit 30c30c7747

View File

@ -0,0 +1,125 @@
---
layout: ../../../../layouts/ApiLayout.astro
---
import Code from "../../../../components/Code.astro"
# `Array.fold`
Reduces the elements of this array into a single value
by calling a function on each element, starting from
the left.
## Signature
<Code thpcode={`
fun fold[A, B](
self[A],
B init,
(B acc, A next) -> (B) transform_function,
) -> B
`} />
## Parameters
- `self`: The callee.
- `init`: The initial value of the fold.
- `transform_function`: The function to apply to every element.
## Return value
- If `self` is an empty array, returns `init`
- Otherwise, returns the result of applying `transform_function` to the accumulator `acc`,
and the next element `next`.
## Description
Fold allows you to transform an array of `A` into a single `B`, following
an arbitraty function.
For example, let's say that you have an array of numbers:
<Code thpcode={`
val digits = [1, 9, 9, 5]
`} />
And you want to join all digits into a String like `"1985"`. You can
achieve this with a fold.
<Code thpcode={`
val digits = [1, 9, 8, 5]
val init = ""
fun f(String acc, Int next) = acc ++ next
digits.fold("", f) // "1985"
`} />
- `f` is a function that takes a previous value (known as the accumulator)
and a new value (known as `next`) and concatenates them.
So `f("", 1)` results in `"1"`, `f("1", 2)` in `"12"` and so on.
---
- To begin, the accumulator is set to `init`, in this case `""`
- First, `f` is called with the accumulator (`""`) and the first
element of the array (`1`) resulting in `f("", 1)`
- This results in the string `"1"`. This becomes the new value of the accumulator.
- Then `f` is called with the accumulator and the 2nd element of the array.
This results in `f("1", 9)`, which is `"19"`. This is now the accumulator.
- Then, `f` is called the same way as before, resulting in `f("19", 8)`.
The accumulator now is `"198"`.
- Finally, `f` is called the same way, resulting in `f("198", 5)` which is `"1985"`.
This is the value that `fold` returns.
A sort of visualization is the following:
```php
[1, 9, 8, 5].fold("", f) =
f( f( f( f("", 1), 9), 8), 5)
f( f( f( "1" , 9), 8), 5)
f( f( "19" , 8), 5)
f( "198" , 5)
"1985"
```
Hopefully now you understand how a fold works, and we can continue using the
abstraction.
---
The `transform_function` can be any function, and can operate over any type.
For example, you could sum all numbers instead of concatenating
like this:
<Code thpcode={`
val digits = [1, 9, 8, 5]
digits.fold(0, fun(acc, next) = acc + next) // 23
`} />
```php
f( f( f( f(0, 1), 9), 8), 5)
f( f( f( 1 , 9), 8), 5)
f( f( 10 , 8), 5)
f( 18 , 5)
23
```
Or you could pass the digits to a builder class:
<Code thpcode={`
val digits = [1, 9, 8, 5]
val builder = ThingBuilder()
digits.fold(builder, fun(acc, next) = acc.addNumber(next))
val result = builder.build()
`} />
Or anything.