Skip to content

Commit

Permalink
Add RFC option-result-map-or-default.
Browse files Browse the repository at this point in the history
  • Loading branch information
orlp committed Jul 14, 2021
1 parent 5e8a06f commit c0544ce
Showing 1 changed file with 82 additions and 0 deletions.
82 changes: 82 additions & 0 deletions text/0000-option-result-map-or-default.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
- Feature Name: `option_result_map_or_default`
- Start Date: 2021-07-14
- RFC PR: [rust-lang/rfcs#0000](/~https://github.com/rust-lang/rfcs/pull/0000)
- Rust Issue: [rust-lang/rust#0000](/~https://github.com/rust-lang/rust/issues/0000)

# Summary
[summary]: #summary

`Option` has the methods `unwrap`, `unwrap_or`, `unwrap_or_else` and `unwrap_or_default`. It
similarly has `map`, `map_or`, `map_or_else`, however `map_or_default` is missing. The exact same
problem exists for `Result`. This RFC is a proposal to add this method to `Option` and `Result`.

# Motivation
[motivation]: #motivation

As mentioned before, a user might reasonably expect this method to exist, based on the existence of
other `or_default` methods such as `unwrap_or_default`. Furthermore, this is a very common usecase.
Searching for `map_or_else` in `.rs` files in the official Rust repository it is incredibly common
to see instances like these:

```rust
.map_or_else(String::new, ...)
.map_or_else(SmallVec::new, ...)
.map_or_else(Vec::new, ...)
```

In fact, from a manual count at the time of writing, 25 out of the 57 occurrences of `map_or_else`
in the Rust codebase could have been replaced with an equivalent call to `map_or_default`.

# Reference-level explanation
[reference-level-explanation]: #reference-level-explanation

The following implementation would get added to `core::option::Option`:

```rust
impl<T> Option<T> {
pub fn map_or_default<U: Default, F: FnOnce(T) -> U>(self, f: F) -> U {
match self {
Some(t) => f(t),
None => Default::default(),
}
}
}
```

The following implementation would get added to `core::result::Result`:

```rust
impl<T, E> Result<T, E> {
pub fn map_or_default<U: Default, F: FnOnce(T) -> U>(self, f: F) -> U {
match self {
Ok(t) => f(t),
Err(e) => Default::Default(),
}
}
}
```

# Drawbacks
[drawbacks]: #drawbacks

It adds another method to `Option` and `Result`, which may be considered as cluttered by some.

# Rationale and alternatives
[rationale-and-alternatives]: #rationale-and-alternatives

- `.map_or_else(Default::default, ...)` can be written, although it is significantly longer.
- In case `feature(default_free_fn)`, stabilized a user can write `.map_or_else(default, ...)`
after `std::default::default`, which is a bit shorter.

However, neither alternative solves the discrepancy between `unwrap_or_default` existing but
`map_or_default` not existing.

# Prior art
[prior-art]: #prior-art

We already have `unwrap_or_default`.

# Unresolved questions
[unresolved-questions]: #unresolved-questions

None.

0 comments on commit c0544ce

Please sign in to comment.