I'm writing an interpreter for a DSL and I ran into a problem where I want to compare two values of unknown type. I have tried to reduce the problem to the following.
I want to define a function with two parameters with the following specification.
public boolean isMinimumOrThrow(Object minToCheck, Collection<Object> coll);
- If
minToCheckis not of typeComparable<?>, then I want to throw a runtime exception. - Otherwise, I want to filter out all objects in
collthat I can compare withminToCheck, and then return whetherminToCheckis less than or equal to every comparable object incoll.
First attempt
I get in trouble when defining the filter, i.e.,
public boolean isMinimumOrThrow(Object minToCheck, Collection<Object> coll) {
if (!(minToCheck instanceof Comparable<?>)) {
throw new RuntimeException();
}
Comparable<?> comparableMin = (Comparable<?>)minToCheck;
return coll.stream().filter(...).allMatch(item -> comparableMin.compareTo((...)item) <= 0);
}
I'm not sure whether it's possible to implement the ....
Second attempt
To work around the problem, I've tried to loosen the restriction of Comparable a bit, and defined my own interface MyComparable<T>
public interface MyComparable<T> extends Comparable<T> {
public Collection<T> filterComparable(Collection<?> values);
}
but even then, I still get a type error
The method compareTo(capture#13-of ?) in the type Comparable<capture#13-of ?> is not applicable for the arguments (capture#12-of ?)
with the following code
public boolean isMinimumOrThrow(Object minToCheck, Collection<Object> coll) {
if (!(minToCheck instanceof MyComparable<?>)) {
throw new RuntimeException();
}
MyComparable<?> comparableMin = (MyComparable<?>)minToCheck;
return comparableMin.filterComparable(coll).stream().allMatch(item -> comparableMin.compareTo(item) <= 0);
}
Any ideas?
Maybe there is a cleaner solution, but you could stick to your first attempt. The filter can be implemented by simply trying a
compareToin a try-catch. This in turn only compiles if you use rawComparablein intermediate steps. The result will be typesafe again (I hope), but needs to suppress some warnings for the intermediate steps. So my suggestion is the following: