# [−][src]Crate these

# These

`These`

represents a 3-way split of data. Think of it as a `Result`

except that we have an extra case that can contain both the result `T`

and
the error `E`

. This can be useful for when we can still compute the final result
but we have also encountered an error.

enum These<T, U> { This(T), That(U), Both(T, U) }

We have three constructors `This`

which holds a `T`

, `That`

which holds a `U`

,
and [`Both`

] which holds both.

# Here and There

If we want to talk about all `T`

s we use the terminology `Here`

. So this
means we either have a `This`

or [`Both`

]. Or in code:

use these::These; fn is_here<T: Copy, U: Copy>(these: &These<T, U>) -> bool { these.is_this() || these.is_these() }

If we want to talk about all `U`

s we use the terminology `There`

. So this
means we either have a `That`

or [`Both`

]. Or in code

use these::These; fn is_here<T: Copy, U: Copy>(these: These<T, U>) -> bool { these.is_that() || these.is_these() }

# Contrived Example

Let us say that we have a function that only allows numbers that are less than
10. We expose a new type `LessThanTen`

and expect our users to use `is_less_than_ten`

to validate `i8`

s into this type. We can use `Result`

and model this below:

#[derive(Debug, PartialEq)] struct LessThanTen(i8); #[derive(Debug, PartialEq)] pub enum Error { IsGreaterThanOrEqualToTen, } pub fn is_less_than_ten(i: i8) -> Result<LessThanTen, Error> { if i < 10 { Ok(LessThanTen(i)) } else { Err(Error::IsGreaterThanOrEqualToTen) } } assert_eq!(is_less_than_ten(8), Ok(LessThanTen(8))); assert_eq!(is_less_than_ten(10), Err(Error::IsGreaterThanOrEqualToTen));

But after a while we realise we can start to support all numbers that are less than 20.
We can do a similar approach, but we would like to be backwards compatible, and also keep
track of when we encounter numbers that are greater than 10. Maybe we would like to keep
statistics on these errors, or convert successful results to `LessThanTen`

for backwards
compatibility. We can use `These`

to solve this and can modelled as below:

use these::These; #[derive(Debug, PartialEq)] struct LessThanTen(i8); #[derive(Debug, PartialEq)] struct LessThanTwenty(i8); #[derive(Debug, PartialEq)] pub enum Error { IsGreaterThanOrEqualToTen, IsGreaterThanOrEqualToTwenty, } pub fn is_less_than_ten(i: i8) -> Result<LessThanTen, Error> { if i < 10 { Ok(LessThanTen(i)) } else { Err(Error::IsGreaterThanOrEqualToTen) } } pub fn is_less_than_twenty(i: i8) -> These<Error, LessThanTwenty> { if i < 10 { These::That(LessThanTwenty(i)) } else if i < 20 { These::Both(Error::IsGreaterThanOrEqualToTen, LessThanTwenty(i)) } else { These::This(Error::IsGreaterThanOrEqualToTwenty) } } // Convert to the backwards compatible scenario pub fn backwards_compatible(r: These<Error, LessThanTwenty>) -> Result<LessThanTen, Error> { r.collapse_these( |e| Err(e), |LessThanTwenty(i)| Ok(LessThanTen(i)), |e, _| Err(e), ) } assert_eq!(is_less_than_ten(8), Ok(LessThanTen(8))); assert_eq!(is_less_than_ten(10), Err(Error::IsGreaterThanOrEqualToTen)); assert_eq!(is_less_than_twenty(8), These::That(LessThanTwenty(8))); assert_eq!(is_less_than_twenty(10), These::Both(Error::IsGreaterThanOrEqualToTen, LessThanTwenty(10))); assert_eq!(is_less_than_twenty(20), These::This(Error::IsGreaterThanOrEqualToTwenty)); assert_eq!(backwards_compatible(is_less_than_twenty(8)), Ok(LessThanTen(8)));

## Enums

These |