Last active
August 29, 2015 13:58
-
-
Save johnlcox/d6dded9807c5f6580626 to your computer and use it in GitHub Desktop.
Java 8 Pattern Matching
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import static GuavaOptionalPattern.caseNone; | |
import static GuavaOptionalPattern.caseSome; | |
import static IntegerPattern.caseOf; | |
import static OrRelsePattern.orElse; | |
import static PatternMatching.match; | |
import com.google.common.base.Optional; | |
public class Examples { | |
public String matchInteger(int x) { | |
return match(x).on( | |
caseOf(1, x -> "one"), | |
caseOf(2, x -> "two"), | |
orElse(_ -> "many") | |
); | |
} | |
public String matchOptionalString(Optional<String> opt) { | |
return match(opt).on( | |
caseSome(str -> str), | |
caseNone(() -> "No String") | |
); | |
} | |
public void runExamples() { | |
System.out.println(matchInteger(3)); | |
System.out.println(matchOptionalString(Optional.of("Hello World")) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// TODO: Needs work. Do the generics actually work out? Is it possible to get a class cast exception with this? | |
public class GuavaOptionalPattern<T> implements Pattern<T> { | |
public static <S, T> Pattern<T> caseSome(Function<S, T> function) { | |
return new GuavaOptionalPresentPattern<S, T>(function); | |
} | |
public static <S, T> Pattern<T> caseNone(Supplier<T> supplier) { | |
return new GuavaOptionalAbsentPattern<S, T>(supplier); | |
} | |
private static class GuavaOptionalPresentPattern<S, T> implements Pattern<T> { | |
private final Function<S, T> function; | |
private GuavaOptionalPresentPattern(Function<S, T> function) { | |
this.function = function; | |
} | |
public boolean matches(Object value) { | |
return value.isInstanceOf(Optional.class) && ((Optional<S>) value).isPresent(); | |
} | |
public T apply(Object value) { | |
return function.apply((T) ((Optional<S>) value).get()); | |
} | |
} | |
private static class GuavaOptionalAbsentPattern<S, T> implements Pattern<T> { | |
private final Supplier<T> supplier; | |
public GuavaOptionalAbsentPattern(Supplier<T> supplier) { | |
this.supplier = supplier; | |
} | |
public boolean matches(Object value) { | |
return value.isInstanceOf(Optional.class) && !((Optional<S>) value).isPresent(); | |
} | |
public T apply(Object value) { | |
return supplier.get(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class IntegerPattern<T> implements Pattern<T> { | |
private final Integer value; | |
private final Function<Integer, T> function; | |
private IntegerPattern(Integer value, Function<Integer, T> function) { | |
this.value = value; | |
this.function = function; | |
} | |
public static <T> Pattern<T> caseOf(int value, Function<Integer, T> function) { | |
return new IntegerPattern<T>(value, function); | |
} | |
public static <T> Pattern<T> caseOf(Integer value, Function<Integer, T> function) { | |
return new IntegerPattern<T>(value, function); | |
} | |
public boolean matches(Object value) { | |
return value.equals(value); | |
} | |
public T apply(Object value) { | |
return function.apply((Integer) value); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ListPattern { | |
public static <S, T> Pattern<T> caseHeadTail(Function<S, List<S>, T> function) { | |
} | |
public static <S, T> Pattern<T> caseNil(Supplier<T> supplier) { | |
} | |
public static <S, T> Pattern<T> caseOf2(Function<S, S, T> function) { | |
} | |
public static <S, T> Pattern<T> caseOf3(Function<S, S, S, T> function) { | |
} | |
public static <S, T> Pattern<T> caseOf4(Function<S, S, S, S, T> function) { | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class MatchingException extends RuntimeException { | |
public MatchingException(String message) { | |
super(message); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class OrElsePattern<T> implements Pattern<T> { | |
private final Function<Object, T> function; | |
private OrElsePattern(Function<Object, T> function) { | |
this.function = function; | |
} | |
public static <T> Pattern<T> orElse(Function<Object, T> function) { | |
return new OrElsePattern<T> function); | |
} | |
public boolean matches(Object value) { | |
return true; | |
} | |
public T apply(Object value) { | |
return function.apply(value); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface Pattern<T> { | |
public boolean matches(Object value); | |
public T apply(Object value); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class PatternMatching { | |
private final Object value; | |
private PatternMatching(Object value) { | |
this.value = value; | |
} | |
public static PatternMatching match(Object value) { | |
return new PatternMatching(value); | |
} | |
public <T> on(Pattern<T>... patterns) { | |
for (Pattern<T> pattern : patterns) { | |
if (pattern.matches(value)) { | |
return pattern.apply(value); | |
} | |
} | |
throw new MatchException("no match for " + value); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment