chj_rustbin/alternatively.rs
1// #[macro_export]
2// macro_rules! alternatively {
3// { $e1:tt, $var:ident : $E:ty => $e2:tt } => {
4// (|| -> Result<_, $E> {
5// Ok($e1)
6// })().or_else(|$var: $E| -> Result<_, bool> {
7// Ok($e2)
8// })
9// }
10// }
11
12/// Try two approaches to generate `T`, if both fail, return the error
13/// of the second attempt (but `f2` could embed the error of the first
14/// attempt in that).
15pub fn alternatively_with_error<T, E1, E2>(
16 f1: impl FnOnce() -> Result<T, E1>,
17 f2: impl FnOnce(E1) -> Result<T, E2>,
18) -> Result<T, E2> {
19 f1().or_else(f2)
20}
21
22/// Try two approaches to generate `T`, if both fail, return the error
23/// of the second attempt (but `f2` could embed the error of the first
24/// attempt in that). Unlike `alternatively_with_error`, this function
25/// forces the error type of both closures to be the same; this is
26/// less flexible but has the advantage that the error type for the
27/// second closure doesn't have to be specified if it specifies it as
28/// the argument.
29pub fn alternatively_with_same_error_type<T, E>(
30 f1: impl FnOnce() -> Result<T, E>,
31 f2: impl FnOnce(E) -> Result<T, E>,
32) -> Result<T, E> {
33 f1().or_else(f2)
34}
35
36// want to just specify E.
37// and both functions just thunks.
38// Best we can do is to specify _ for T at the call site.
39
40/// Try two argument-less functions of the same function type to
41/// generate `T`, if both fail, return the error of the second attempt
42/// (the first error is lost).
43pub fn alternatively<T, E>(
44 f1: impl FnOnce() -> Result<T, E>,
45 f2: impl FnOnce() -> Result<T, E>,
46) -> Result<T, E> {
47 f1().or_else(|_| f2())
48}