Another thing Todd and I talked about briefly a
while back. I'm adding it here for
documentation...
Arrays are objects with a particular subtyping
semantics (and corresponding instanceof
behavior), according to Java. There's no reason
not to permit people to write external methods
on array types:
int String[].find(String toFind) { ... }
It even makes sense to have dispatch:
class A {}
class B extends A {}
boolean A[].foo() {}
boolean A[]@B[].foo() {}
class X {
boolean bar(A[] a_arr) {} // (1)
boolean bar(A[]@B[] b_arr) {} // (2)
}
"But," one might object, "it's not sound!" Well,
actually, it's no more unsound than Java's
existing semantics. Any lvalue use of a_arr[i] in
(1) above is unsound, just as any lvalue use of
b_arr[i] in (2) is unsound. Conversely
(assuming you used instanceof tests to
dispatch), any rvalue use of b_arr[i] in (2) *is*
sound, just as any rvalue use of a_arr[i] in (1) is
sound.
Finally, why not allow external functions
(although not dispatching) on primitive types,
and arrays thereof?
boolean char.isWhitespace() {
return Character.isWhitespace(this);
}
int char[].find(char toFind) { ... }
None of these enhancements are fundamental
to MJ, of course, but they would be nice. And
they take MJ one step closer to eliminating
spurious static utility functions. (There are good
reasons for some static utility functions to
exist---classes provide namespace control, and
can store static state that persists across
invocations---but stateless public static utility
functions should be eliminated.)