gleam-lang / gleam-lang/stdlib

Add `option.replace`

Open
#917 2 comments 1 reaction 0 assignees View on GitHub
Dominant language
Gleam
Stars
710
Forks
225
Avg merge
5h 52m
Merged PRs (30d)
3

Description

`result.replace` and `result.replace_error` both exist in the stdlib. The `Option` type has no equivalent, so replacing the inner value of a `Some` while preserving the `Some`/`None` structure requires `option.map` with a throwaway argument:

```gleam
option.map(protected.kid, fn(_) { "kid" })
```

This comes up when converting optional fields to presence indicators. For example, collecting the names of whichever optional header fields are set:

```gleam
let optional_headers =
option.values([
option.map(protected.kid, fn(_) { "kid" }),
option.map(protected.typ, fn(_) { "typ" }),
option.map(protected.cty, fn(_) { "cty" }),
])
```

The `fn(_) { ... }` adds noise without adding meaning. With `option.replace`, these read as:

```gleam
let optional_headers =
option.values([
option.replace(protected.kid, "kid"),
option.replace(protected.typ, "typ"),
option.replace(protected.cty, "cty"),
])
```

The implementation mirrors `result.replace` exactly, substituting `Some`/`None` for `Ok`/`Error`:

```gleam
/// Replaces the value inside a `Some`, leaving `None` unchanged.
///
/// ## Examples
///
/// ```gleam
/// assert replace(Some(1), "a") == Some("a")
/// ```
///
/// ```gleam
/// assert replace(None, "a") == None
/// ```
///
pub fn replace(option: Option(a), value: b) -> Option(b) {
case option {
Some(_) -> Some(value)
None -> None
}
}
```

The `map` with `fn(_)` workaround shows up whenever optional fields need to be projected to fixed values while retaining the original field values. In my case, this was constructing CBOR maps from optional claims.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.