The aim of the Maybe type is to avoid using 'null' references.
A Maybe
A Maybe
A Maybe
class Customer {
public Maybe
for (String emailAddress : aCustomer.emailAddress()) { sendEmailTo(emailAddress); }
Maybe
For example, if I have a collection of 'maybe' email addresses, some of which might exist and some might not:
Iterable<Maybe<String>> maybeEmailAddresses = ...
I can get a set of only the actual email addresses in a single expression:
Set<String> actualEmailAddresses = newHashSet(concat(maybeEmailAddresses));
The newHashSet and concat functions are defined by Guava. Concat
creates an Iterable
More likely, I have an iterable collection of Customers. Using a Function, I can write a single expression to get the email addresses of all customers who have an email address:
Here's a function to map a customer to its 'maybe' email address:
Function<Customer,Maybe
And here's how to use it to get all the email addresses that my customers have, so I can send them product announcements:
Set
If I just want to send emails, I don't need the hash set:
for (String emailAddress : concat(transform(customers, toEmailAddress))) { sendEmailTo(emailAddress); }
The name "concat" is a bit obscure, so I'd probably define an alias named, for example, "definite", to make the code more readable at the point of use. And the Function definition is a bit clunky, but Java doesn't have (and doesn't look likely to get) a clean syntax for referring to existing functions.
That's not to say that Maybe doesn't have useful methods to work with individual instances. For example, the otherwise method:
T otherwise(T defaultValue);
will return the Maybe's value if it is known and the defaultValue if it is not. E.g.
assertThat(unknown().otherwise(""), equalTo(""));
assertThat(definitely("foo").otherwise(""), equalTo("foo"));
Otherwise is overloaded to take a Maybe
Maybe
which lets you chain otherwise expressions:
assertThat(unknown().otherwise(definitely("X")).otherwise(""), equalTo("X"));
Maybe also has a method that uses a function to map a Maybe
<U> Maybe<U> to(Function<T,U> mapping);
which would transform unknown() to unknown(), otherwise apply the function to the definite value and return the result wrapped in a Maybe.
Similarly there is a query method that takes a Predicate
All of which API calls make it impossible (without deliberate effort) to try to get the value of nothing.