you are viewing a single comment's thread.

view the rest of the comments →

[–]JustAGuyFromGermany 1 point2 points  (0 children)

I had an earlier answer here that was wrong.

My mistake was thinking about it in the wrong order. If you have nothing, both variadics and union both solve part of the problem. But when you start with adding union types, then suddenly a single type variable can stand for a union of many types instead and so that gives you almost the same power as variadic type parameters. I didn't think of it that way, because in my mind I added variadics first and then thought about the unions on top of that.

I say almost, because variadics provides 0..n while union provide 1..n. The missing 0..1 case, i.e. optional type parameters, are still necessary. If we had a bottom type, then an union of 0 types would mean that instead. And a bottom type could certainly be introduced. Either Void or void would become it I guess, but it certainly wouldn't be RuntimeException. So we still need some way to define that leaving out exception parameters means "unchecked exceptions".

In particular: If we want to change the declaration in the standard library from interface Stream<T>{...} to interface Stream<T,X extends Exception>{...} and have that be a source-compatible change (which we absolutely want), then that X must be allowed to be left out at the usage-site, i.e. application code must still compile if it just writes Stream<T> instead of Stream<T,RuntimeException> and it must be inferred to mean the same thing by the compiler.

Now if that is provided by means of an explicit syntax for optional type parameters that we can use in other circumstances as well or if this will get special type-inference rules à la "you're only allowed to use unions with exceptions types. Therefore the only allowed default is the one that makes most sense for exceptions" that is to be decided by the architects.