# \[Pre-RFC\] Option::for\_some

**URL:** <https://internals.rust-lang.org/t/pre-rfc-option-for-some/12974>\
**Category:** libs\
**Created:** [August 28, 2020, 9:15pm UTC](https://internals.rust-lang.org/t/pre-rfc-option-for-some/12974 "2020-08-28T21:15:23Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![pdolezal](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/pdolezal/32/7137_2.png) [@pdolezal](https://internals.rust-lang.org/u/pdolezal)\
**Post date:** [August 28, 2020, 9:15pm UTC](https://internals.rust-lang.org/t/pre-rfc-option-for-some/12974/1 "2020-08-28T21:15:23Z")

</div>

- Feature Name: option\_for\_some
- Start Date: 2020-08-28
- RFC PR:
- Rust Issue:

# Summary

This RFC proposes the addition of `Option::for_some`.

# Motivation

`Option` lacks an operation that consumes the value in a similar way as `Iterator::for_each`. It is possible to use `if let`:

```rust
fn main() {
    let number: Option<u32> = Some(42);

    if let Some(even) = number.filter(|n| n % 2 == 0) {
        println!("{} is even", even);
    }
}

```

However, this expression can be quite mouthful and does feel good when chaining multiple operations. Where a similar chain with an `Iterator` could simply resort to `for_each`, `Option` offers nothing. With `Option::for_some` the example above could be more compact:

```rust
fn main() {
    let number: Option<u32> = Some(42);

    number
        .filter(|n| n % 2 == 0)
        .for_some(|even| println!("{} is even", even));
}

```

A trait-based implementation of the `for_some` function:

```rust
pub trait OptionForSome<T> {
    fn for_some<F: FnOnce(T)>(self, f: F);
}

impl<T> OptionForSome<T> for Option<T> {
    fn for_some<F: FnOnce(T)>(self, f: F) {
        if let Some(value) = self {
            f(value);
        }
    }
}

```

# Rationale and alternatives

This would provide a compact alternative to `if let` construction to consume `Some(value)`. The alternative could be more ergonomic and natural in operation chains. It would provide a match for `Iterator::for_each` as well.

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [August 28, 2020, 9:20pm UTC](https://internals.rust-lang.org/t/pre-rfc-option-for-some/12974/2 "2020-08-28T21:20:39Z")

</div>

As far as I can tell, this is the `Option::map` function, minus the return value.

```rust
fn main() {
    Some(42).filter(|x| x % 2 == 0).map(|x| println!("{} is even", x));
}

```

---

<div class="post-metadata">

**Author:** ![pdolezal](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/pdolezal/32/7137_2.png) [@pdolezal](https://internals.rust-lang.org/u/pdolezal)\
**Post date:** [August 28, 2020, 9:24pm UTC](https://internals.rust-lang.org/t/pre-rfc-option-for-some/12974/3 "2020-08-28T21:24:56Z")

</div>

You are right, but there are some points why `map` IMO does not feel right:

- This might be just subjective, but I'd expect `map` to map the values, while `for_some` is more focused on side-effects. It is a "terminal" operation.
- The example with `map` instead causes Clippy to be [unhappy](https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unit_fn).
- With the respect to Clippy, I'd argue that `for_some` indicates better the intent of consuming the value.

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [August 28, 2020, 9:29pm UTC](https://internals.rust-lang.org/t/pre-rfc-option-for-some/12974/4 "2020-08-28T21:29:03Z")

</div>

I'm not sure I'd agree with that clippy lint.

In any case, I'm not expressing strong opposition to the proposed method (though I'd probably nitpick the name a little). I'm more suggesting that _if_ we were to have it, it'd likely be implemented as "map with a different name and without the return value", and we should evaluate it accordingly.

On a different note, I'd also like to have a `try_map` function, which would allow using a function that can fail with an error, and would return `Result<Option<_>, _>` rather than `Option<Result<_, _>>`, so that `.try_map(...)?` would work.

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [August 28, 2020, 9:30pm UTC](https://internals.rust-lang.org/t/pre-rfc-option-for-some/12974/5 "2020-08-28T21:30:31Z")

</div>

A way to make clippy happy is `x.map_or((), |y| ...)`.

---

<div class="post-metadata">

**Author:** ![pdolezal](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/pdolezal/32/7137_2.png) [@pdolezal](https://internals.rust-lang.org/u/pdolezal)\
**Post date:** [August 28, 2020, 9:36pm UTC](https://internals.rust-lang.org/t/pre-rfc-option-for-some/12974/6 "2020-08-28T21:36:26Z")

</div>

> On a different note, I'd also like to have a `try_map` function, which would allow using a function that can fail with an error, and would return `Result<Option<_>, _>` rather than `Option<Result<_, _>>` , so that `.try_map(...)?` would work.

I'd probably need a more complete example to see where `transpose` would not work for you.

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [August 28, 2020, 9:37pm UTC](https://internals.rust-lang.org/t/pre-rfc-option-for-some/12974/7 "2020-08-28T21:37:34Z")

</div>

> [@josh](#):
>
> On a different note, I'd also like to have a `try_map` function, which would allow using a function that can fail with an error

you can `.map(...).transpose()`

_Edit:_ @pdolezal was faster

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [August 28, 2020, 10:55pm UTC](https://internals.rust-lang.org/t/pre-rfc-option-for-some/12974/8 "2020-08-28T22:55:49Z")

</div>

It would work, it's just less convenient, less self-explanatory, and more opaque.

Much the same reason you're asking for `for_some` when we already have `map`.

Which looks clearer?

```rust
let y = some_opt.try_map(|x| {
    foo(x)?;
    Ok(bar(x)?)
})?;

```

vs

```rust
let y = some_opt.map(|x| {
    foo(x)?;
    Ok(bar(x)?)
})
.transpose()?;

```

---

<div class="post-metadata">

**Author:** ![elidupree](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/elidupree/32/4304_2.png) [@elidupree](https://internals.rust-lang.org/u/elidupree)\
**Post date:** [August 29, 2020, 12:04am UTC](https://internals.rust-lang.org/t/pre-rfc-option-for-some/12974/9 "2020-08-29T00:04:06Z")

</div>

> [@pdolezal](#):
>
> The example with `map` instead causes Clippy to be [unhappy](https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unit_fn).

> [@josh](#):
>
> I'm not sure I'd agree with that clippy lint.

Moreover, if one _does_ agree with the clippy lint, then the exact _same_ readability concern would apply to all possible usages of `for_some()`.

I've used `Option::map` like this and it seems suitable. Iterators need a separate `for_each` method because `Iterator::map` is lazy, but `Option::map` isn't, and the name "for\_some" isn't the most immediately recognizable as to its meaning. If you need to be explicit, there's always `option.into_iter().for_each()`, which is very clear about its intent and only a smidgen more verbose.

---

<div class="post-metadata">

**Author:** ![pdolezal](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/pdolezal/32/7137_2.png) [@pdolezal](https://internals.rust-lang.org/u/pdolezal)\
**Post date:** [August 29, 2020, 9:55am UTC](https://internals.rust-lang.org/t/pre-rfc-option-for-some/12974/10 "2020-08-29T09:55:28Z")

</div>

I'll try to summarize the replies and arguments raised so far with some comments. Feel free to comment the summary and bring more thoughts 🙂

* * *

# `Option::map` does the same job.

Both `map` and `for_some` invoke an operation that consumes the contained value. However, `map` produces another `Option` with the operation result. As the name suggests, `map` is supposed to map values, so that the outcome could be used in chained calls. On the contrary, `for_each` is supposed to consume the value and produces nothing useful (as far as we could consider `()` here as nothing).

# Clippy warning seems confusing.

If `map` should be used for consuming the value, statements like `option.map(|value| foo(value));` should not issue any warning.

If `for_some` existed, the warning still makes sense, although it could be refined in the sense that the result of `map` is not used and the intent is not clear (for instance: does it mean that someone forgot to use it or does it mean that `map` has some side effect?) and there are clearer alternatives like `if let Some(value)` and `for_some`.

# Use `option.into_iter().for_each()` instead.

A hard argument against this idea is that `Iterator::for_each` takes `FnMut`, while `for_some` takes `FnOnce` as it can take the advantage of at-most-once invocation.

A soft argument is that converting `Option` into `Iterator` just to consume the at most one value seems too convoluted and instead of indicating the intent clearly and expressing it in a compact way, it brings more complexity. I'd guess that a newbie could think: _Why the heck an iterator appears here?_

# Name is confusing.

Naming is always somewhat subjective, but as long as most users agree that the name fits the intent and feels good in the code, I guess the name is fine. I would trust English native speakers more with the name choice than I trust myself. Anyway, let me share some of my (subjective) reasons for choosing `for_some`.

I like `Option::for_some` mostly because it's similarity with `Iterator::for_each` (and it seems to me natural as well). I considered a few other names, the most serious alternative was `if_some`, which nicely resembles the `if let Some(value)` pattern, but nothing in `std` starts `if_`, so it feels less familiar. Maybe yet, `if_some` feels like there should be `if_none` as well (I don't have the feeling with `for_some`, since `for_none` looks weird) and this way leads to ugly ends (basically poking users to avoid `match` for `Option` even when it is clean).

I'm not in favor in using `map` as a part of the proposed operation's name. I guess it is obvious from the first point's summary: I feel `map` should _map_ a value, while this operation is supposed to _consume_ a value. I considered even `consume` as the name. Maybe some people would like it more.

* * *

Just a final footnote about `try_map` that @josh mentioned as something similar. I think his idea is closer to the case of `filter_map`, which allows using `filter` and `map` used in conjunction in a more user friendly way. Then `try_map` could be understood as a similar operation with the respect to `map` and `transpose` (if I interpret it correctly). Anyway, I see no strong links to proposing `for_some` and I don't think the proposals must be necessarily judged together.

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [August 29, 2020, 10:15am UTC](https://internals.rust-lang.org/t/pre-rfc-option-for-some/12974/11 "2020-08-29T10:15:13Z")

</div>

You didn't pick up my suggestion of using `.map_or((), ...)`.

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [August 29, 2020, 10:18am UTC](https://internals.rust-lang.org/t/pre-rfc-option-for-some/12974/12 "2020-08-29T10:18:06Z")

</div>

A question: what would be the `Result` equivalent(s) of this? Usually they parallel each other fairly closely in the methods on offer (as in many ways `Option<T> <=> Result<T, ()>`) so whether `for_ok`/`for_err` would be good/bad things might be indirect evidence for/against this method.

> [@pdolezal](#):
>
> I considered a few other names, the most serious alternative was `if_some` , which nicely resembles the `if let Some(value)` pattern, but nothing in `std` starts `if_` , so it feels less familiar.

Note that `.for_each()` on iterators didn't exist for a long time, with the advice being to just use a for loop: [Add for\_each function to Iterator trait by aochagavia · Pull Request #14911 · rust-lang/rust · GitHub](https://github.com/rust-lang/rust/pull/14911#issuecomment-46119797)

That only changed thanks to two things: 1) rayon's ParallelIterator has it, so it's helpful when switching between that and Iterator 2) there are some iterators where internal iteration is more efficient. Notably the "better for chaining" argument never tipped the scales.

`Option::map` has value in that it avoids needing to specify `else { None }`, but `else { () }` is implicit so that doesn't apply to `Option::for_some`. And there's no rayon or internal iteration argument for this method.

---

<div class="post-metadata">

**Author:** ![pdolezal](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/pdolezal/32/7137_2.png) [@pdolezal](https://internals.rust-lang.org/u/pdolezal)\
**Post date:** [August 29, 2020, 10:39am UTC](https://internals.rust-lang.org/t/pre-rfc-option-for-some/12974/13 "2020-08-29T10:39:50Z")

</div>

Ah, sorry 😳 I guess I could make a poll. Perhaps some more suggestions will yet arrive.

* * *

Edit:

I missed your point, probably was already too tired 🙄 I agree that `option.map_or((), |value| use(value))` is a quite nice alternative. Another way to make Clippy happy is to assign & forget: `let _ = option.map(|value| use(value))`.

The assign & forget still seems to me not very nice. I admit that `map_or` looks better, but I'm still not convinced that it voids the value of `for_some` completely. But I will use it until `for_some` is available 😉

---

<div class="post-metadata">

**Author:** ![pdolezal](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/pdolezal/32/7137_2.png) [@pdolezal](https://internals.rust-lang.org/u/pdolezal)\
**Post date:** [August 29, 2020, 10:45am UTC](https://internals.rust-lang.org/t/pre-rfc-option-for-some/12974/14 "2020-08-29T10:45:04Z")

</div>

Good remarks and questions. I didn't know the history – thanks. I will have to think your questions over.

Regarding the "better for chaining" argument: it might not be raised then, especially when it was (maybe?) not so well established, but it might be valid and it might be valid even more now.

---

<div class="post-metadata">

**Author:** ![pdolezal](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/pdolezal/32/7137_2.png) [@pdolezal](https://internals.rust-lang.org/u/pdolezal)\
**Post date:** [August 29, 2020, 8:36pm UTC](https://internals.rust-lang.org/t/pre-rfc-option-for-some/12974/15 "2020-08-29T20:36:13Z")

</div>

@scottmcm I have some answer, maybe not very satisfying, but I didn't want to leave your question unanswered.

> A question: what would be the `Result` equivalent(s) of this? Usually they parallel each other fairly closely in the methods on offer (as in many ways `Option<T> <=> Result<T, ()>`) so whether `for_ok/for_err` would be good/bad things might be indirect evidence for/against this method.

I'm not entirely sure if something like `for_ok` would have a good meaning or use. I agree with you that similarity between these types should be considered, so I guess I should bring some arguments why `Option::for_some` makes sense, while `Result::for_ok` probably not. Although there are similarities, there are differences as well (why to have two types otherwise, right?). This might be one of the cases where the differences show up.

The primary meaning of `Result` is representing success or failure. Uses of `Result` are focused on function results and processing them in a safe way. Ignoring `Result` smells, the cases where neither `Ok` nor `Err` need _any_ processing are probably very rare. `Err` cases can be thrown away easily with `?` operator, focusing the code flow on the happy path and the `Ok` value.

How the hypothetic `Result::for_ok` could be helpful and how it would fit in? I would expect it to help consuming the `Ok` value and I would expect both these options to work as noted:

```rust
// Handle Err as usual
fallible_operation().for_ok(|ok| println!("We successfully generated {}.", ok))?;

// Ignore Err completely
fallible_operation().for_ok(|ok| println!("We successfully generated {}.", ok));

```

In both cases the value of the statement would be `()`. Compare it to the code without `for_ok`:

```rust
// Handling Err
let ok = fallible_operation()?;
println!("We successfully generated {}.", ok);
// Alternatively
println!("We successfully generated {}.", fallible_operation()?);

// Ignoring Err
if let Ok(ok) = fallible_operation() {
    println!("We successfully generated {}.", ok);
}

```

When handling `Err`, `for_ok` does not help much in my opinion. However, with `for_ok` it is easy to ignore `Err`, even by an accident. It seems dangerous to me and I think this looks like KO for `for_ok`.

Regarding `for_err`, I think it is a lost case from the beginning and not just because `for_ok` seems to lead in a bad direction. As I noted before, I don't see something like `Option::for_none` as a good idea. The less reasons there I would expect in favor of `Result::for_err`.

Why the failure with `Result::for_ok` might not be relevant for rejecting `Option::for_some`? `Option` is more generic and it does not (or should not) indicate success/failure. Therefore not acting on `None` (or `Option` in general) does not smell like ignoring `Err` (or `Result` in general). So, a short answer might be: because `for_some` brings no danger.

By the way, `for_some` could indirectly extend the possibilities of `Result`:

```rust
// Ignore Err completely, but in a safer way
fallible_operation()
    .ok()
    .for_some(|ok| println!("We successfully generated {}.", ok));

```

---

<div class="post-metadata">

**Author:** ![HarrisonMc555](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/harrisonmc555/32/7066_2.png) [@HarrisonMc555](https://internals.rust-lang.org/u/HarrisonMc555)\
**Post date:** [September 2, 2020, 10:31pm UTC](https://internals.rust-lang.org/t/pre-rfc-option-for-some/12974/16 "2020-09-02T22:31:27Z")

</div>

I don't know if there's an explicit statement about this value somewhere, but I think in general, Rust tends to favor "brace" statements for side effects over eager, chained method calls. One example would be that this:

```rust
for x in foos().map(bar) {
    baz(x);
}

```

is typically preferred over:

```rust
foos().map(bar).for_each(baz);

```

Maybe that's just my personal preference shining through, but I thought I read about that somewhere in the Rust book or something like that 🤷‍♂️ I personally think it helps emphasize the fact that we're depending on side effects rather than traditional "functional-esque" (no side-effect) programming.

This would be analogous to how this:

```rust
if let Some(x) = foo().bar() {
    baz(x);
}

```

would be preferable over this:

```rust
foo().bar().for_some(baz);

```

I can empathize that it would be nice if there were an analogous method, though, for nothing other than consistency 😄

---

<div class="post-metadata">

**Author:** ![InfernoDeity](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/infernodeity/32/7588_2.png) [@InfernoDeity](https://internals.rust-lang.org/u/InfernoDeity)\
**Post date:** [September 20, 2020, 12:10am UTC](https://internals.rust-lang.org/t/pre-rfc-option-for-some/12974/17 "2020-09-20T00:10:03Z")

</div>

This honestly has precedent in java, with java.util.Optional::ifPresent, which accepts a `Consumer<T>` (which is effectively, at least here, an FnOnce(T)-\>()). Similar to here, it can be done using the stream api (comparable to rust Iterators). I'd support it at least on the prior art side

---

<div class="post-metadata">

**Author:** ![pdolezal](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/pdolezal/32/7137_2.png) [@pdolezal](https://internals.rust-lang.org/u/pdolezal)\
**Post date:** [September 20, 2020, 8:48am UTC](https://internals.rust-lang.org/t/pre-rfc-option-for-some/12974/18 "2020-09-20T08:48:24Z")

</div>

> [@InfernoDeity](#):
>
> This honestly has precedent in java, with java.util.Optional::ifPresent, which accepts a `Consumer<T>` (which is effectively, at least here, an FnOnce(T)-\>()). Similar to here, it can be done using the stream api (comparable to rust Iterators). I'd support it at least on the prior art side

Yes, you are right. I didn't mention that deliberately, but it might be a good point after all.

I'll try to explain in detail for those less familiar with Java. `Optional::ifPresent` is basically a must, just compare:

```java
// With ifPresent
thatOptional.ifPresent(System.out::println);

```

```java
// Without ifPresent
if (thatOptional.isPresent()) {
    System.out.println(thatOptional.get());
}

```

`Optional::get` is like `Option::unwrap`, throwing an exception when there is nothing to unwrap. Hence just seeing it makes one more suspicious.

`Optional::map` can't work here, because `map` must return something, but `System.out::println` has `void` return type, which means it returns literally nothing. Yes, not having a unit type is a tragedy. On the other hand, it is obvious that the operation in `ifPresent` has side effects (because it can't return anything), while `map` with its `Function` argument type is generally expected to rather avoid side effects (it is not forbidden, but it is not considered nice either).

It was mentioned the possibility of turning an `Option` into an iterator and using `Iterator::for_each`. This is possible with `Optional` too (since Java 9):

```java
thatOptional.stream().forEach(System.out::println);

```

Still, `Optional::stream` is never used like this and it exists mostly for using with `Stream::flatMap` to extract values from a `Stream<Optional>` (I guess everybody can imagine it).

The case of Java `Optional` shows a few reasons that are not applicable for Rust (like mitigating its awkwardness with the respect to the language's other features) and these reasons led me rather not using it as an argument. Instead, I tried to pick the reasons that I considered valid for Rust as well:

- A more compact invocation of operations that consume `Option`'s value.
- A distinct operation that is supposed to have side effects (unlike `map` and friends).
- An analogy to `Iterator::for_each`, but a better alternative to the proposal of using `option.iter().for_each(…)`, which would be more compact and which would allow `FnOnce` instead of `FnMut`.

Anyway, I'm biased: Java is my bread and buffer and therefore the chained-method-invocation style with a terminal operation like `ifPresent` might feel more natural for me than for other developers using Rust. I tried, meanwhile, using `Option::map_or` instead, as I was suggested, and although it works, kind of, I still feel not comfortable enough. The distinct semantics of `ifPresent`/`for_some` is missing. So I hope that `Option::for_some` still may bring some value.

---

<div class="post-metadata">

**Author:** ![Tom-Phinney](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tom-phinney/32/3299_2.png) [@Tom-Phinney](https://internals.rust-lang.org/u/Tom-Phinney)\
**Post date:** [September 20, 2020, 1:31pm UTC](https://internals.rust-lang.org/t/pre-rfc-option-for-some/12974/19 "2020-09-20T13:31:20Z")

</div>

Thank you for the educational explanation. It makes sense.

---

<div class="post-metadata">

**Author:** ![phlopsi](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/phlopsi/32/7393_2.png) [@phlopsi](https://internals.rust-lang.org/u/phlopsi)\
**Post date:** [September 20, 2020, 3:23pm UTC](https://internals.rust-lang.org/t/pre-rfc-option-for-some/12974/20 "2020-09-20T15:23:25Z")

</div>

I'd probably use [apply](https://docs.rs/apply/0.3.0/apply/trait.Apply.html) and do `my_option.map(…).apply(drop);`.

[Next page](https://internals.rust-lang.org/t/pre-rfc-option-for-some/12974.md?page=2)
