Skip to content

Commit 1a666a7

Browse files
committed
EitherOrBoth: Add or and or_else methods to simplify getting default values
1 parent 2357d1a commit 1a666a7

File tree

1 file changed

+49
-0
lines changed

1 file changed

+49
-0
lines changed

src/either_or_both.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,33 @@ impl<A, B> EitherOrBoth<A, B> {
164164
}
165165
}
166166

167+
/// Returns a tuple consisting of the `l` and `r` in `Both(l, r)`, if present.
168+
/// Otherwise, returns the wrapped value for the present element, and the supplied
169+
/// value for the other. The first (`l`) argument is used for a missing `Left`
170+
/// value. The second (`r`) argument is used for a missing `Right` value.
171+
///
172+
/// Arguments passed to `or` are eagerly evaluated; if you are passing
173+
/// the result of a function call, it is recommended to use [`or_else`],
174+
/// which is lazily evaluated.
175+
///
176+
/// [`or_else`]: EitherOrBoth::or_else
177+
///
178+
/// # Examples
179+
///
180+
/// ```
181+
/// # use itertools::EitherOrBoth;
182+
/// assert_eq!(EitherOrBoth::Both("tree", 1).or("stone", 5), ("tree", 1));
183+
/// assert_eq!(EitherOrBoth::Left("tree").or("stone", 5), ("tree", 5));
184+
/// assert_eq!(EitherOrBoth::Right(1).or("stone", 5), ("stone", 1));
185+
/// ```
186+
pub fn or(self, l: A, r: B) -> (A, B) {
187+
match self {
188+
Left(inner_l) => (inner_l, r),
189+
Right(inner_r) => (l, inner_r),
190+
Both(inner_l, inner_r) => (inner_l, inner_r),
191+
}
192+
}
193+
167194
/// Returns a tuple consisting of the `l` and `r` in `Both(l, r)`, if present.
168195
/// Otherwise, returns the wrapped value for the present element, and the [`default`](Default::default)
169196
/// for the other.
@@ -178,6 +205,28 @@ impl<A, B> EitherOrBoth<A, B> {
178205
EitherOrBoth::Both(l, r) => (l, r),
179206
}
180207
}
208+
209+
/// Returns a tuple consisting of the `l` and `r` in `Both(l, r)`, if present.
210+
/// Otherwise, returns the wrapped value for the present element, and computes the
211+
/// missing value with the supplied closure. The first argument (`l`) is used for a
212+
/// missing `Left` value. The second argument (`r`) is used for a missing `Right` value.
213+
///
214+
/// # Examples
215+
///
216+
/// ```
217+
/// # use itertools::EitherOrBoth;
218+
/// let k = 10;
219+
/// assert_eq!(EitherOrBoth::Both("tree", 1).or_else(|| "stone", || 2 * k), ("tree", 1));
220+
/// assert_eq!(EitherOrBoth::Left("tree").or_else(|| "stone", || 2 * k), ("tree", 20));
221+
/// assert_eq!(EitherOrBoth::Right(1).or_else(|| "stone", || 2 * k), ("stone", 1));
222+
/// ```
223+
pub fn or_else<L: FnOnce() -> A, R: FnOnce() -> B>(self, l: L, r: R) -> (A, B) {
224+
match self {
225+
Left(inner_l) => (inner_l, r()),
226+
Right(inner_r) => (l(), inner_r),
227+
Both(inner_l, inner_r) => (inner_l, inner_r),
228+
}
229+
}
181230
}
182231

183232
impl<T> EitherOrBoth<T, T> {

0 commit comments

Comments
 (0)