In a recent post, I was talking about a micro DSL to create a simple “find x in a list” service. The key thing here is that it defines how to look for x in the list. So the list can be a list of anything, not just a list of x’s.
Just to recap then, to find something in a list, the original client code (using a static import) looks like this.
The class (in this case
NeedleFinder) implements the DSL and specifically decides in the
in method how to compare a
Needle object to whatever is in the haystack list. I wanted to create a more generic class so started to implement the
ListFinder to use generics and a couple of interesting things came out.
The generified class looks like this.
With the following test case showing its usage (the
Bale class aren’t show for brevity).
Here we’re defining the equality of a
Needle in a list of
Bale objects to be when the name of a
Needle is contained in the name of the
Bale. A silly example I know but it illustrates that we redefine what we mean by equality for the list finder by implementing the
ListFinder.Comparator. The concrete example that spawned the idea was when searching for a
Race object inside a list of
Event objects; two completely different entities.
Type inference over too many types
Anyway, what I thought was interesting about this example was the type inference going on in the static find method. I originally wanted to just use
ListFinder.find method directly as in the following.
ListFinder is statically imported. Usually, I’d rely on type inference here to work out that needle means
T and therefore
T is of type
Needle. However, in the case above, the compiler will complain as the haystack parameter is not of type
Object. The trick is that the generic method
ListFinder needs to infer two types (
L) but only has enough information for
T. So it defaults
L to type
The alternative is to use the full notation as follows.
Or (as I’ve done in the test) use an internal method who’s return type gives the compiler enough information to infer both types. I prefer this approach as it makes the DSL expression to find a needle much more readable.
So, Java can’t chain methods to infer the types. I didn’t really expect it to be able to so, its a bit much to ask for. Although it would be pretty sweet if it could.
One last thing, Ray Barlow was showing me a Jedi alternative to the finder. If we’re lucky, he might blog about it. It seems Jedi offers some measure of residence against the proliferation of anonymous inner classes in lieu of closures but in all honestly, I just wanted to get in some big words in before signing off. TTFN.
- Domain Specific Languages (Addison-Wesley Signature), Martin Fowler
- DSLs in Action, DSLs in Action
- The Definitive ANTLR 4 Reference: Building Domain-Specific Languages (Pragmatic Programmers), Terence Parr