Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't Scala "handle" ClassTags automatically?

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.

like image 379
Erik Kaplun Avatar asked Feb 10 '14 17:02

Erik Kaplun


1 Answers

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...

like image 93
Vladimir Matveev Avatar answered Nov 15 '22 04:11

Vladimir Matveev