Skip to content

Instantly share code, notes, and snippets.

@fsarradin
Created July 27, 2012 11:19
Show Gist options
  • Save fsarradin/3187455 to your computer and use it in GitHub Desktop.
Save fsarradin/3187455 to your computer and use it in GitHub Desktop.
Option with flatMap
package collect;
import com.google.common.base.Function;
public abstract class Option<T> {
private static final Option<?> ABSENT = new Absent<Object>();
public static <T> Option<T> of(T value) {
return new Present<T>(value);
}
public abstract T get();
public abstract Option<T> flatMap(Function<T, Option<T>> function);
public abstract boolean isPresent();
public static <T> Option<T> absent() {
return (Option<T>) ABSENT;
}
private static class Present<T> extends Option<T> {
private final T value;
public Present(T value) {
this.value = value;
}
@Override
public T get() {
return value;
}
@Override
public Option<T> flatMap(Function<T, Option<T>> function) {
return function.apply(value);
}
@Override
public boolean isPresent() {
return true;
}
}
private static class Absent<T> extends Option<T> {
@Override
public T get() {
throw new UnsupportedOperationException();
}
@Override
public Option<T> flatMap(Function<T, Option<T>> function) {
return (Option<T>) ABSENT;
}
@Override
public boolean isPresent() {
return false;
}
}
}
package collect;
import static org.fest.assertions.Assertions.assertThat;
import javax.annotation.Nullable;
import org.junit.Test;
import com.google.common.base.Function;
public class OptionExtremeTest {
@Test
public void should_get_3_by_iterative_flatMap() {
Option<Integer> result = Option.of(1).flatMap(add(2));
assertThat(result.isPresent()).isTrue();
assertThat(result.get()).isEqualTo(3);
}
private Function<Integer, Option<Integer>> add(final Integer i) {
return new Function<Integer, Option<Integer>>() {
@Override
public Option<Integer> apply(@Nullable Integer x) {
return Option.of(x + i);
}
};
}
@Test
public void should_get_3_by_recursive_flatMap() {
Option<Integer> result = Option.of(1).flatMap(new Function<Integer, Option<Integer>>() {
@Override
public Option<Integer> apply(@Nullable final Integer x) {
return Option.of(2).flatMap(new Function<Integer, Option<Integer>>() {
@Override
public Option<Integer> apply(@Nullable final Integer y) {
return Option.of(x + y);
}
});
}
});
assertThat(result.isPresent()).isTrue();
assertThat(result.get()).isEqualTo(3);
}
}
package collect;
import static org.fest.assertions.Assertions.assertThat;
import javax.annotation.Nullable;
import org.junit.Test;
import com.google.common.base.Function;
public class OptionTest {
private static final Function<String, Option<String>> ID_FUNCTION = new Function<String, Option<String>>() {
@Override
public Option<String> apply(@Nullable String value) {
return Option.of(value);
}
};
private static final Function<String,Option<String>> FAIL_FUNCTION = new Function<String, Option<String>>() {
@Override
public Option<String> apply(@Nullable String _) {
return Option.absent();
}
};
@Test
public void should_flatMap_when_present() {
Option<String> result = Option.of("hello").flatMap(ID_FUNCTION);
assertThat(result.isPresent()).isTrue();
assertThat(result.get()).isEqualTo("hello");
}
@Test
public void should_not_flatMap_when_absent() {
Option<String> result = Option.<String>absent().flatMap(ID_FUNCTION);
assertThat(result.isPresent()).isFalse();
}
@Test
public void should_not_flatMap_when_fail_on_present() {
Option<String> result = Option.of("hello").flatMap(FAIL_FUNCTION);
assertThat(result.isPresent()).isFalse();
}
@Test
public void should_not_flatMap_when_fail_on_absent() {
Option<String> result = Option.<String>absent().flatMap(FAIL_FUNCTION);
assertThat(result.isPresent()).isFalse();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment