9

RFC: add `try_all` and `try_any` to `Iterator` by FlixCoder · Pull Request #3233...

 2 years ago
source link: https://github.com/rust-lang/rfcs/pull/3233
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Copy link

FlixCoder commented 10 days ago

edited by shepmaster

rendered

As this is my first RFC / PR here, I am sorry if there is something missing or wrong.

Thank you for reviewing and suggestions :)

FlixCoder

changed the title Proposal to add try_all and try_any to Iterator

RFC: add try_all and try_any to Iterator

10 days ago

In some cases where one would like to use `any`/`all`, the actual condition to check is fallible. For example, let's say we have a simple key-value-store like a `HashMap`. The keys are IDs to the objects. We further have a list of IDs we want to check some condition on. We would like to use `all` on an iterator over the list to ensure all objects match our condition. However, access to elements is fallable and returns `Option`s. In other cases, the checks might involve more complex validation on the objects. The validation method could involve access to external parts and fail. Therefore, it returns a `Result<bool, Error>`.

The implementor needs to return a `bool` for every element in `all`. They could use `.try_fold(true, |state, item| Ok(state && check(item)?))`, but this is less readable and does not short-circuit as `all` does. If they would do `.all(|item| check(item).unwrap_or(false))`, the error would be discarded and lost/ignored. To fully comply with expectations, there is only two possibilites (I see):

Short-circuiting on both is probably easiest done with try_for_each, something like

    let r = it.try_for_each(|x| match check(x) {
        Ok(b) => if b { ControlFlow::Continue(()) } else { ControlFlow::Break(Ok(false)) },
        e => ControlFlow::Break(e),
    });
    let r = match r {
        ControlFlow::Continue(()) => Ok(true),
        ControlFlow::Break(r) => r,
    };

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=746bd31e2418ffacdff08855c91e6205

But yes, that's of course much less readable than having the method provided by Iterator.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK