Class tags seem to be really easy to use, however, is it not mathematically possible to always reliably automatically insert the ClassTag
boilerplate in at least some scenarios if not all? Consider this example:
def foo[T: ClassTag] = {
val cls = classTag[T].runtimeClass.asInstanceOf[Class[T]]
val myList: Seq[T] = parseList(rawJson, cls) // let's assume parseList a library method that needs to work with a Class instance (e.g. RestFB's fetchConnnection)
...
}
why wouldn't Scala let me write instead:
def foo[T] = {
val cls = classOf[T]
val myList: Seq[T] = parseList(rawJson, cls) // let's assume parseList a library method that needs to work with a Class instance (e.g. RestFB's fetchConnnection)
...
}
...and transform the latter to the former automatically?
Is there a technical reason for this, e.g. the desirability of class tags cannot always be reliably determined by the compiler/reflection library? Or it's purely a conscious design choice to keep this explicit? For example to encourage the programmer to avoid the need to use class tags in the first place for a cleaner design and better performance, even if it's known that in many cases it's not possible?
P.S. I'm not asking why Scala doesn't (nor proposing it should) add the ClassTag
magic to every method definition with a generic type parameter; I'm merely asking why it couldn't be done automatically when it's needed/unavoidable.
This syntax:
def foo[T: ClassTag] = ...
in fact is a shorthand for this one:
def foo[T](implicit ev: ClassTag[T]) = ...
This means if ClassTag[T]
were supplied for every generic type parameter, then every function would have additonal hidden parameter, or even several.
This is of course completely undesirable. One of the most prominent downsides of this approach is nearly ruined Java interoperability when using generics:
SomeClass someClass = new SomeClass();
someClass.foo<Integer>(ClassTag.apply(Integer.class));
Imagine more advanced generic methods and parameters. And this is only for the ability to match on generic type, which is almost never needed.
Calling Java generic methods would also be ambigous. Which method should be called here:
val jc = new JavaClass
jc.foo[Int]()
if JavaClass
is defined like this:
public class JavaClass {
public <T> void foo() { ... }
public <T> void foo(ClassTag<T> ct) { ... }
}
?
Of course, if Java supported reified generics, everything would be different...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With