Skip to content

Instantly share code, notes, and snippets.

@jonseymour
Created March 6, 2012 10:16
Show Gist options
  • Save jonseymour/1985544 to your computer and use it in GitHub Desktop.
Save jonseymour/1985544 to your computer and use it in GitHub Desktop.
Option v2
With getters exposed as meta data, one can write an expression like this.
final Option<String> opt = OptionFactory.option(foo).with(FooMeta.getBar.deref(BarMeta.getName));
final String name = opt.isSome() ? opt.some() : "";
useName(name);
or:
final String name = OptionFactory.option(foo).with(FooMeta.getBar.deref(BarMeta.getName)).orAlternate("");
useName(name);
or:
for (String name : OptionFactory.option(foo).with(FooMeta.getBar.deref(BarMeta.getName))) {
useName(name);
return;
}
useName("");
or (less likely):
OptionFactory.option(foo).with(FooMeta.getBar.deref(BarMeta.getName)).with(new UnaryOp<String.Void>() {
public Void apply(String name) {
useName(name);
}
});
package org.jonseymour.v1.option;
import java.util.NoSuchElementException;
import org.jonseymour.v1.functional.Unary;
import org.junit.Test.None;
/**
* Defines an {@link Option} type.
* <p>
* Several access patterns are supported.
* <p>
* The Iterable pattern:
* <pre>
* // assuming Option&lt;T&gt; foo()
*
* for (T t : foo()) {
* doSomething(t);
* return;
* }
* doDefaultThing();
* </pre>
* <p>
* The 'with Unary' pattern:
* </p>
* <pre>
* Option&lt;String&gt; opt = foo()
* .with(FooMeta.getBar)
* .with(BarMeta.getName);
* </pre>
* The 'checked access' pattern:
* <pre>
* final Option&lt;Tgt; opt = foo();
* opt.some(); // illegal: access to some() not guarded by call to isSome(), isNone().
* if (opt.isSome()) {
* final T t = opt.some();
* doSomething(t);
* } else {
* doDefaultThing();
* }
* </pre>
* The 'orAlternate' pattern:
* <pre>
* final Option&lt;String&gt; opt = foo();
* final String someString = opt.orAlternate("");
* </pre>
*
*
* </pre>
* @author jseymour
* @inspiredBy http://eng.wealthfront.com/2010/05/better-option-for-java.html
* @param <T>
*/
public interface Option<T>
extends Iterable<T>, Cloneable
{
public abstract Option<T> clone();
/**
* Execute the specified {@link Unary} with the {@link Impl}'s value, if
* there is one. Return an Option with an instance of the {@link Unary}'s
* output type.
* <p>
* If the {@link Impl} does not have a value, return {@link None} without
* running the {@link Unary}.
*
* @param unary
* The unary operation to be called, if Option has a value.
* @return An instance of Option&lt;O&gt;.
*/
public abstract <O> Option<O> with(Unary<T, O> unary);
/**
* @return Answers true if there is a non-null value associated with the {@link Impl}.
*/
public abstract boolean isSome();
/**
* @return Answers true if there is no non-null value associated with the {@link Impl}.
*/
public abstract boolean isNone();
/**
* Answers the {@link Impl}'s value.
*
* @return Answers a reference to the value, but only if isNone() and isSome() has been called first.
* @throws NoSuchElementException If isNone() is false or if isSome() or isNone() has not been called immediately before a call to this method.
*/
public abstract T some();
/**
* Answers either the receiver's value (if not null) or <code>alternate</code> otherwise.
*
* @param alternate An alternate value which must not be null.
* @return The {@link Impl}'s value or <code>alternate</code>, if the receiving {@link Impl} {@link #isNone()}.
* @throws IllegalArgumentException if <code>alternate</code> is null.
*/
public abstract T orAlternate(T alternate);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment