Created
November 13, 2013 17:51
-
-
Save apskii/7453335 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 apsk.jpatmat; | |
| import java.util.ArrayList; | |
| import java.util.List; | |
| import java.util.Random; | |
| import java.util.function.Consumer; | |
| import java.util.function.Function; | |
| public class Entry { | |
| // Simple Arithmetic Language | |
| static abstract class Term { | |
| // Hybrid Matcher | |
| public <R> R match( | |
| Function<Lit, R> f1, | |
| Function<Sum, R> f2, | |
| Function<Mul, R> f3 | |
| ) { | |
| if (this instanceof Lit) | |
| return f1.apply((Lit) this); | |
| else if (this instanceof Sum) | |
| return f2.apply((Sum) this); | |
| else if (this instanceof Mul) | |
| return f3.apply((Mul) this); | |
| return null; | |
| } | |
| } | |
| static abstract class PairTerm extends Term { | |
| public final Term fst; | |
| public final Term snd; | |
| public PairTerm(Term fst, Term snd) { | |
| this.fst = fst; | |
| this.snd = snd; | |
| } | |
| } | |
| static class Sum extends PairTerm { | |
| public Sum(Term fst, Term snd) { super(fst, snd); } | |
| @Override public String toString() { | |
| return "(" + fst.toString() + " + " + snd.toString() + ")"; | |
| } | |
| } | |
| static class Mul extends PairTerm { | |
| public Mul(Term fst, Term snd) { super(fst, snd); } | |
| @Override public String toString() { | |
| return "(" + fst.toString() + " * " + snd.toString() + ")"; | |
| } | |
| } | |
| static class Lit extends Term { | |
| public final int val; | |
| public Lit(int val) { | |
| this.val = val; | |
| } | |
| @Override public String toString() { | |
| return String.valueOf(val); | |
| } | |
| } | |
| // Generic Lambda Pattern-Matcher | |
| static <I, R, | |
| T1 extends I, | |
| T2 extends I, | |
| T3 extends I | |
| > | |
| R match(I x, | |
| Class<T1> c1, Function<T1, R> f1, | |
| Class<T2> c2, Function<T2, R> f2, | |
| Class<T3> c3, Function<T3, R> f3 | |
| ) { | |
| Class<?> c = x.getClass(); | |
| if (c.isAssignableFrom(c1)) | |
| return f1.apply((T1) x); | |
| else if (c.isAssignableFrom(c2)) | |
| return f2.apply((T2) x); | |
| else if (c.isAssignableFrom(c3)) | |
| return f3.apply((T3) x); | |
| return null; | |
| } | |
| // Eval with Generic Matcher | |
| static int eval(Term term) { | |
| return match(term, | |
| Lit.class, lit -> lit.val, | |
| Sum.class, sum -> eval(sum.fst) + eval(sum.snd), | |
| Mul.class, mul -> eval(mul.fst) * eval(mul.snd) | |
| ); | |
| } | |
| // Eval with Static Matcher | |
| static int evalInstanceof(Term term) { | |
| if (term instanceof Lit) | |
| return ((Lit) term).val; | |
| else if (term instanceof Sum) | |
| return evalInstanceof(((Sum) term).fst) + evalInstanceof(((Sum) term).snd); | |
| else if (term instanceof Mul) | |
| return evalInstanceof(((Mul) term).fst) * evalInstanceof(((Mul) term).snd); | |
| return -111; | |
| } | |
| // Eval with Hybrid Matcher | |
| static int evalSM(Term term) { | |
| return term.match( | |
| lit -> lit.val, | |
| sum -> evalSM(sum.fst) + evalSM(sum.snd), | |
| mul -> evalSM(mul.fst) * evalSM(mul.snd) | |
| ); | |
| } | |
| // Generate randomized terms | |
| static List<Term> mkTerms(int count) { | |
| Random rndGen = new Random(); | |
| ArrayList<Term> terms = new ArrayList<>(count); | |
| for (int i = 0; i < count; ++i) | |
| terms.add( | |
| new Sum( | |
| new Lit(1), | |
| new Mul( | |
| new Lit(rndGen.nextInt(20)), | |
| new Sum( | |
| new Lit(3), new Lit(4) | |
| ) | |
| ) | |
| ) | |
| ); | |
| return terms; | |
| } | |
| // Turn function to an action, performed specified number of times | |
| static <I,R> Consumer<I> times(int count, Function<I,R> f) { | |
| return x -> { | |
| for (int i = 0; i < count; ++i) f.apply(x); | |
| }; | |
| } | |
| public static void main(String[] args) { | |
| List<Term> terms = mkTerms(1000000); | |
| System.out.println("1,000,000 terms initialized..."); | |
| for (int n = 1; n < 1000; n *= 10) { | |
| System.out.println("[ " + n + " evals ]:"); | |
| long startMillis = System.currentTimeMillis(); | |
| terms.forEach(times(n, Entry::eval)); | |
| System.out.println("Generic: " + (System.currentTimeMillis() - startMillis)); | |
| startMillis = System.currentTimeMillis(); | |
| terms.forEach(times(n, Entry::evalInstanceof)); | |
| System.out.println("Static: " + (System.currentTimeMillis() - startMillis)); | |
| startMillis = System.currentTimeMillis(); | |
| terms.forEach(times(n, Entry::evalSM)); | |
| System.out.println("Hybrid: " + (System.currentTimeMillis() - startMillis)); | |
| System.out.println(); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment