I'm trying to see if the template expression pattern can be imitated in Java, to do optimizations like loop fusion.
As an example, I port the c++ classes found in this expression template example to java classes: https://en.wikipedia.org/wiki/Expression_templates#Motivation_and_example
First, a template class VecExpression<E> representing a vector expression. It uses a template parameter E and takes the class type of E as a constructor parameter. It then creates a private variable thisAsE set to this cast to the class type of E
public abstract class VecExpression <E> {
private VecExpression thisAsE;
public VecExpression(Class<E> type) throws Exception {
if(type.isInstance(this)) {
thisAsE = (VecExpression)type.cast(this);
}
else {
throw new Exception("Class type must extend VecExpression");
}
}
public double get(int i) {
return thisAsE.get(i);
}
public int size() {
return thisAsE.size();
}
}
Second, a class Vec extending VecExpression<Vec> which passes Vec.class into the super constructor and implements the get() and size() methods called in the VecExpression<E> class.
public class Vec extends VecExpression<Vec> {
private double[] elems;
public <E> Vec(VecExpression<E> expression) throws Exception {
super(Vec.class);
for(int i = 0; i < expression.size(); ++i) {
elems[i] = expression.get(i);
}
}
public Vec(double[] elems) throws Exception {
super(Vec.class);
this.elems = elems;
}
public double get(int i) {
return elems[i];
}
}
And third, a template class VecSum<E1, E2> which extends VecExpression<VecSum<E1, E2>, and uses its get() method to return the sum of two VecExpression<E>s. The type is passed as an explicit parameter Class<VecSum<E1, E2>> type.
public class VecSum <E1, E2> extends VecExpression<VecSum<E1, E2>> {
private VecExpression u;
private VecExpression v;
public VecSum(Class<VecSum<E1, E2>> type, VecExpression<E1> u, VecExpression<E2> v) throws Exception {
super(type);
if(u.size() != v.size()) {
throw new Exception("Vectors must be of the same size");
}
this.u = u;
this.v = v;
}
public double get(int i) {
return u.get(i) + v.get(i);
}
public int size() {
return v.size();
}
}
Finally, we use the expression template to generate a class that can add three vectors with a single pass through memory.
public class Main {
public static void main(String[] args) throws Exception {
Vec a = new Vec(new double[] {1, 2, 3});
Vec b = new Vec(new double[] {1, 2, 3});
Vec c = new Vec(new double[] {1, 2, 3});
VecSum<Vec, Vec> ab = new VecSum<Vec, Vec>(VecSum<Vec, Vec>.class, a, b);
VecSum<VecSum<Vec, Vec>, Vec> abc = new VecSum<>(VecSum<VecSum<Vec, Vec>, Vec>.class, ab, c);
}
}
EDITED as per Louis Wasserman's comment
However, the class types passed into the VecSum constructor don't work because the expression is trying to get a class from a parameterized type. Louis pointed out that implementations of a generic class don't compile to different classes like they do in c++. How would you pass their type, or is there another approach to the expression template pattern?
ArrayList. It just legacy code you don't get this checking and you had to explicitly cast the result of things likeget.