|
Re: pattern-matching is a bit low-level
|
Posted: Jul 3, 2006 2:43 PM
|
|
I think Scala is an excelent language and that it will influence future languages greatly. Having said that I agree with Pasko Robert who said he prefered Multiple Dispatch to patterns. The patterns example is coded below using my Pattern Enforcing Compiler (PEC):
http://pec.dev.java.net/nonav/compile/index.html
that implements the Multiple Dispatch pattern on top of standard Java.
public interface TermMD extends pec.compile.multipledispatch.MultipleDispatch { // The methods in this interface are Multiply Dispatched
Term binarySimplify( Term toTheLeft, Term toTheRight );
Term unarySimplify( Term toTheRight );
}
public interface Term extends TermMD { // The method in this interface is Singly Dispatched
Term simplify();
}
public abstract class TerminalTerm implements Term {
public final Term binarySimplify( Term toTheLeft, Term toTheRight ) { throw new AssertionError(); } // Method body replaced by PEC - with a multiple dispatch call
public static final Term binarySimplify( final Term kind, final Term toTheLeft, final Term toTheRight ) { return kind; } // Default simplifier for unary terms - do nothing
public final Term unarySimplify( Term toTheRight ) { throw new AssertionError(); } // Method body replaced by PEC - with a multiple dispatch call
public static final Term unarySimplify( final Term kind, final Term toTheRight ) { return kind; } // Default simplifier for binary terms - do nothing
public Term simplify() { return this; } // Nothing to simplify for a terminal!
}
public abstract class UnaryTerm extends TerminalTerm {
protected final Term toTheRight;
protected UnaryTerm( final Term toTheRight ) { this.toTheRight = toTheRight.simplify(); }
public Term simplify() { return unarySimplify( toTheRight ); }
}
public abstract class BinaryTerm extends UnaryTerm {
protected final Term toTheLeft;
protected BinaryTerm( final Term toTheLeft, final Term toTheRight ) {
super( toTheRight );
this.toTheLeft = toTheLeft.simplify();
}
public Term simplify() { return binarySimplify( toTheLeft, toTheRight ); }
}
public final class Zero extends TerminalTerm {}
public final class NaN extends TerminalTerm {}
public final class Var extends TerminalTerm {}
public final class Mult extends BinaryTerm {
public Mult( final Term toTheLeft, final Term toTheRight ) { super( toTheLeft, toTheRight ); }
public static final Term binarySimplify( final Mult m, final Zero z, final Term t ) { return z; } // 0 * x = 0
public static final Term binarySimplify( final Mult m, final Term t, final Zero z ) { return z; } // x * 0 = 0
public static final Term binarySimplify( final Mult m, final Zero z, final Zero z2 ) { return z; } // 0 * 0 = 0, needed to resolve conflict
public static final Term binarySimplify( final Mult m, final NaN n, final Term t ) { return n; } // NaN * x = NaN
public static final Term binarySimplify( final Mult m, final Term t, final NaN n ) { return n; } // x * NaN = NaN
public static final Term binarySimplify( final Mult m, final NaN n, final NaN n2 ) { return n; } // NaN * NaN = NaN, needed to resolve conflict
public static final Term binarySimplify( final Mult m, final NaN n, final Zero z ) { return n; } // NaN * 0 = NaN, needed to resolve conflict
public static final Term binarySimplify( final Mult m, final Zero z, final NaN n ) { return n; } // 0 * NaN = NaN, needed to resolve conflict
}
The example is slightly expanded to show how conflicts are handelled. In particular 0 * 0 , 0 * NaN , NaN * 0 , and NaN * NaN . The multiple dispatch methods, the static mathods called binarySimplify and unarySimplify in the code can be in any class and can be seperately compiled. EG the power example:
public final class Power extends BinaryTerm {
public Power( final Term toTheLeft, final Term toTheRight ) { super( toTheLeft, toTheRight ); }
public static final Term binarySimplify( final Mult m, final Power pL, final Power pR ) { // x**z * y**z = (x * y)**z
if ( pL.toTheRight == pR.toTheRight ) return (new Power( new Mult( pL.toTheLeft, pR.toTheLeft ), pL.toTheRight )).simplify();
return m;
}
}
|
|