Java has come a long way in recent years, and with the manifold project, it seems to be taking a leap into the future. Manifold is a Java compiler plugin that supplements Java with cool features like extension methods, properties, Tuple Expressions, operator overloads, unit Expressions, a preprocessor type access to bizarre data formats, and so much more.
Exploring Manifold
Let's dive into some of the manifold's features and see how they can enhance our Java programming experience.
Extension Methods and Properties
With manifold, we can add new methods to existing types. This is done by defining an extensions package and then under that, defining packages that correspond to each element in the fully qualified name of the type that you want to extend. For example, if you want to extend Java util ArrayList, you'll create packages Java, util, and ArrayList. Now you can add new methods to the ArrayList type.
Manifold also allows property dereferencing. You can use the dot notation to access properties by having manifold access the Java Bean accessor method for that property under the hood. This feature doesn't yet seem to work with Java record properties, but it's likely just a matter of time.
##language-java
package extensions.java.util.ArrayList;
import java.util.ArrayList;
public class ArrayListExtension {
public static <E> void printSize(ArrayList<E> list) {
System.out.println("The size of the list is: " + list.size());
}
}
// Usage
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(1);
numbers.add(2);
numbers.printSize(); // prints "The size of the list is: 2"
Tuples
Tuples are a great way to stash variables without the ceremony of a full-on class. They are often seen in languages like Python, especially for data processing scenarios involving lots of chained operations with intermediate tuples. With manifold, there are two varieties of tuples - anonymous tuples where each element gets an accessor and named tuples which are like Maps where the keys are type safe.
##language-xml
import manifold.ext.rt.api.Jailbreak;
import manifold.ext.rt.api.Structural;
@Jailbreak @Structural
public interface Tuple2<A, B> {
A getItem1();
B getItem2();
}
// Usage
Tuple2<String, Integer> tuple = (Tuple2<String, Integer>) new Object();
System.out.println(tuple.getItem1()); // prints null
System.out.println(tuple.getItem2()); // prints null
Units and Measurements
Manifold makes it easy to model units, which is a natural thing in scientific computing. When you want to think about numbers, you can think about numbers in the context of the unit that they apply to. For example, you can easily write out a distance in kilometers.
##language-java
import manifold.science.util.UnitConstants;
import manifold.science.api.Unit;
import manifold.science.measures.Length;
// Usage
Length len = 100.0 * UnitConstants.km;
System.out.println(len.to(UnitConstants.mile)); // prints "62.13711922373339 mile"
Operator Overloading
Manifold allows operator overloading, putting our domain model on equally expressive footing as the likes of your everyday Scholars and strings. You just define some well-known magic functions like plus, and you can rewrite your code to use the appropriate operator instead.
##language-java
import manifold.ext.rt.api.Operator;
import manifold.ext.rt.api.This;
public class Cart {
private int total;
@Operator
public static Cart plus(@This Cart thiz, Cart other) {
Cart newCart = new Cart();
newCart.total = thiz.total + other.total;
return newCart;
}
// getters and setters
}
// Usage
Cart cart1 = new Cart();
cart1.setTotal(100);
Cart cart2 = new Cart();
cart2.setTotal(200);
Cart cart3 = cart1 + cart2;
System.out.println(cart3.getTotal()); // prints "300"
Conclusion
Manifold brings a lot of exciting features to Java, making it more expressive and flexible. While it's still in its early days and there's work to be done, it's definitely worth exploring and could potentially shape the future of Java.