Created
May 11, 2012 10:26
-
-
Save ndemengel/2658827 to your computer and use it in GitHub Desktop.
Towards Pattern Matching in Java - See comment #4 at http://kerflyn.wordpress.com/2012/05/09/towards-pattern-matching-in-java/
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
package snippet; | |
import static snippet.Snippet.ClassPattern.inCaseOf; | |
import static snippet.Snippet.IntegerPattern.inCaseOf; | |
import static snippet.Snippet.OtherwisePattern.otherwise; | |
import static snippet.Snippet.StringPattern.inCaseOf; | |
import com.google.common.base.Function; | |
public class Snippet { | |
public static interface Pattern<R> { | |
boolean matches(Object value); | |
R apply(Object value); | |
} | |
public static class PatternMatching<R> { | |
private final Pattern<R>[] patterns; | |
public PatternMatching(final Pattern<R>... patterns) { | |
this.patterns = patterns; | |
} | |
public R matchFor(final Object value) { | |
for (Pattern<R> pattern : patterns) { | |
if (pattern.matches(value)) { | |
return pattern.apply(value); | |
} | |
} | |
throw new IllegalArgumentException("cannot match " + value); | |
} | |
} | |
public static class ClassPattern<T, R> implements Pattern<R> { | |
private final Class<T> clazz; | |
private final Function<T, R> function; | |
public ClassPattern(final Class<T> clazz, final Function<T, R> function) { | |
this.clazz = clazz; | |
this.function = function; | |
} | |
public boolean matches(final Object value) { | |
return clazz.isInstance(value); | |
} | |
@SuppressWarnings("unchecked") | |
public R apply(final Object value) { | |
return function.apply((T) value); | |
} | |
public static <T, R> Pattern<R> inCaseOf(final Class<T> clazz, final Function<T, R> function) { | |
return new ClassPattern<T, R>(clazz, function); | |
} | |
} | |
public static class StringPattern<R> implements Pattern<R> { | |
private final String pattern; | |
private final Function<String, R> function; | |
public StringPattern(final String pattern, final Function<String, R> function) { | |
this.pattern = pattern; | |
this.function = function; | |
} | |
public boolean matches(final Object value) { | |
return pattern.equals(value); | |
} | |
public R apply(final Object value) { | |
return function.apply((String) value); | |
} | |
public static <R> Pattern<R> inCaseOf(final String pattern, final Function<String, R> function) { | |
return new StringPattern<R>(pattern, function); | |
} | |
} | |
public static class IntegerPattern<R> implements Pattern<R> { | |
private final Integer pattern; | |
private final Function<Integer, R> function; | |
public IntegerPattern(final int pattern, final Function<Integer, R> function) { | |
this.pattern = pattern; | |
this.function = function; | |
} | |
public boolean matches(final Object value) { | |
return pattern.equals(value); | |
} | |
public R apply(final Object value) { | |
return function.apply((Integer) value); | |
} | |
public static <R> Pattern<R> inCaseOf(final int pattern, final Function<Integer, R> function) { | |
return new IntegerPattern<R>(pattern, function); | |
} | |
} | |
public static class OtherwisePattern<R> implements Pattern<R> { | |
private final Function<Object, R> function; | |
public OtherwisePattern(final Function<Object, R> function) { | |
this.function = function; | |
} | |
public boolean matches(final Object value) { | |
return true; | |
} | |
public R apply(final Object value) { | |
return function.apply(value); | |
} | |
public static <R> Pattern<R> otherwise(final Function<Object, R> function) { | |
return new OtherwisePattern<R>(function); | |
} | |
} | |
@SuppressWarnings("unchecked") | |
public static int fact(final int n) { | |
return new PatternMatching<Integer>( // | |
inCaseOf(Integer.class, new Function<Integer, Integer>() { | |
public Integer apply(final Integer x) { | |
return 5 + x; | |
} | |
}), // | |
inCaseOf("", new Function<String, Integer>() { | |
public Integer apply(final String _) { | |
return 1; | |
} | |
}), // | |
inCaseOf(0, new Function<Integer, Integer>() { | |
public Integer apply(final Integer _) { | |
return 1; | |
} | |
}), // | |
otherwise(new Function<Object, Integer>() { | |
public Integer apply(final Object _) { | |
return n * fact(n - 1); | |
} | |
})).matchFor(n); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment