Check out this code.
// Print object and recurse if iterable
private static void deep_print(Object o) {
System.out.println(o.getClass().toString() + ", " + o.toString());
boolean iter = false;
Iterable<?> i1 = null;
Object[] i2 = null;
if (o instanceof Iterable<?>) {
iter = true;
i1 = (Iterable<?>) o;
} else if (o instanceof Object[]) {
iter = true;
i2 = (Object[]) o;
}
if (iter) {
for (Object o_ : i2 == null ? i1 : i2) deep_print(o_); // ERROR: Can only iterate over an array or an instance of java.lang.Iterable
}
I know how to solve it. I just want to know why it happens. Shouldn’t the compiler simply check all the possible outputs?
The static result type of the expression
(i2 == null) ? i1 : i2is the common ancestor ofi1andi2which is Object. Aforstatement requires the static type of the expression to be either anIterableor an array type. That is not the case, so you get a compilation error.Now if you are asking why doesn’t the compiler deduce that
(i2 == null) ? i1 : i2will always be an array or an Iterable:Hypothetically, if the Java type system was a bit different, this particular case could be handled better. Specifically, if Java supported algebraic data types then it would be possible to declare
oas being “either an object array or an iterable” … and theforloop would be type-checkable.1 – Suppose that
ohad been initialized aso = (x * x < 0) ? new Object() : new Object[0]. Determining that that will always result in anObject[]instance entails a small proof involving the fact that the square of a (real) number is not negative. That’s a simple example, it is possible to construct arbitrarily complicated examples requiring arbitrary difficult proofs.2 – The Halting Problem is mathematically proven to be an incomputable function. In other words, there exist functions where it is mathematically impossible to prove whether or not they terminate.