2 ms·
IMO Java's crippling flaw is that it is very verbose (largely but not entirely due to lack of type inference), but its type system nevertheless permits a lot of
by andrewflnr 6y ago
IMO Java's crippling flaw is that it is very verbose (largely but not entirely due to lack of type inference), but its type system nevertheless permits a lot of errors (notably NPEs) that other languages easily catch. In a lot of ways, it gets the worst properties of both static and dynamic languages, both the inflexibility and the unsafety, all the weight and precious little of the power. It would be a lot more tolerable if it was null-safe with proper algebraic Option types.
So yeah, a smart programmer who moves from Java to either Haskell or Clojure will likely find it a breath of fresh air, for very different reasons. Incidentally, the reason I recommend OCaml is because it's a HM-inferred language but with a much more pragmatic type system than Haskell's. You can just println wherever you please.
It's true that subtyping makes inference a lot harder. My reflex is that subtyping is overrated and you should just use interfaces and composition, but you would have a decent claim that I'm moving the goalposts or something. I'm sure OCaml has a semi-decent solution, given the O part of the name, but I don't know off hand what it is. Worst case, if the compiler chokes on your subtype-heavy code I would say to just annotate it. Annotations are certainly valid for when type inference fails or for generally forcing it to do your will in weird cases. Relatedly, I don't totally hate forcing top-level function signatures to be explicit, which would also solve the most-general-interface thing in most cases.
AFAICT your last example is just ill-typed and should not compile. This is another of the places where Java's type system just fails entirely. What is the caller who gets that thing supposed to do with it, except reflect on the type of the contents like we're writing Python?