]> git.lizzy.rs Git - rust.git/commit
Rollup merge of #78455 - udoprog:refcell-opt-map, r=KodrAus
authorMara Bos <m-ou.se@m-ou.se>
Sat, 16 Jan 2021 17:29:45 +0000 (17:29 +0000)
committerGitHub <noreply@github.com>
Sat, 16 Jan 2021 17:29:45 +0000 (17:29 +0000)
commit6bb06f4f2387e2369d98cf87d79b772f99ae979f
treee62c46ec9e6565c5a6bd19593627ee1dea97aa04
parent63a83c5f55801b17b77adf690db397d17c706c48
parentc625b979aed9ad3c8380ea2239d9345d4cec695a
Rollup merge of #78455 - udoprog:refcell-opt-map, r=KodrAus

Introduce {Ref, RefMut}::try_map for optional projections in RefCell

This fills a usability gap of `RefCell` I've personally encountered to perform optional projections, mostly into collections such as `RefCell<Vec<T>>` or `RefCell<HashMap<U, T>>`:

> This kind of API was briefly featured under Open questions in #10514 back in 2013 (!)

```rust
let values = RefCell::new(vec![1, 2, 3, 4]);
let b = Ref::opt_map(values.borrow(), |vec| vec.get(2));
```

It primarily avoids this alternative approach to accomplish the same kind of projection which is both rather noisy and panicky:
```rust
let values = RefCell::new(vec![1, 2, 3, 4]);

let b = if values.get(2).is_some() {
    Some(Ref::map(values.borrow(), |vec| vec.get(2).unwrap()))
} else {
    None
};
```

### Open questions

The naming `opt_map` is preliminary. I'm not aware of prior art in std to lean on here, but this name should probably be improved if this functionality is desirable.

Since `opt_map` consumes the guard, and alternative syntax might be more appropriate which instead *tries* to perform the projection, allowing the original borrow to be recovered in case it fails:

```rust
pub fn try_map<U: ?Sized, F>(orig: Ref<'b, T>, f: F) -> Result<Ref<'b, U>, Self>
where
    F: FnOnce(&T) -> Option<&U>;
```

This would be more in line with the `try_map` method [provided by parking lot](https://docs.rs/lock_api/0/lock_api/struct.RwLockWriteGuard.html#method.try_map).