How are Scala Implicits more explicit than Java Generics?

This blogpost will show you how implicits can solve problems arising from/because of type erasure, proving that Scala implicits sometimes are more explicit than Java generics  (big grin)

All of these code snippets can be copy-pasted to the REPL. Some of the require-s will fail, those are just to demonstrate the expected work without the need of a testing framework.

Scala implicits versus Java generics

Easy, class based ranking

So we need to create a problem for better understanding. Let’s say we have an email app, where we have Mail, and ImportantMail classes, and an Unread trait.

I want to list the mails on the UI by importance, and always want the unread emails higher than the read ones. So the desired sequence would be ImpotantMail with Unread, ImportantMail, Mail with Unread and last but not least Mail.

Our toycode would look like something like this:

It’s not so pretty, I use var, and isInstanceOf, but it does the things I want to, so we will use it as a starting point.

(Ofc this can be achived if the Mail, ImportantMail etc have a rank function. However if the implementation of the data-types can not be modified, you need to come up with something like this.)

So I need to add this functionality to more places

I want to rank my todos or tasks or whatevers with this super ranking algo (smile) So I will modify it a bit. With some generics, it could be used for any classes or traits.

If you run this in REPL, the last require will be ok, but the others drop the IllegalArgumentException. We get a warning as well: “abstract type A is unchecked since it is eliminated by erasure”. What the hell is erasure? And whydid my rank function start to rank everything to 11? Let’s read the java docs about generics. It says that the generated bytecode will use the upper bounds of the generics, in cases where these are not specified (like there) it will use Object. The generated bytecode will be something unexpected at first, like:

That’s bad. Those isInstanceOf checks will be degraded to if(true)-s. How can I match to a generic type?

Scala ClassTags and match-case

So as I said above, the isInstanceOf is evil, and if you want to match classes, you should use match-case instead. The problem with match-case in this particular problem is; it won’t let both cases run, so we need to match twice (sad) (If you know C/C++/C#/Java, all the switch cases can run on multiple branches if you left the break out. Most of the time it’s annoying. You need to type the breaks all the time, and if you forget, you get crazy-hard-to-reproduce bugs.) Our code with match-case:

Still unchecked warnings, and still not working (sad) But we have a special kind of weapon, the ClassTags. Here is the working code:

And yes! Those two little implicits magically solved our problem, and the match started matching again. Before some explanation, we could add a little more refactor:

Much cleaner code, no more var, no more copypasted code, and the requires are still OK. So we can talk about the implicit magic here.

Most of the important points are in the official doc. The ClassTag is a partial type descriptior of the runtime scala type. These tags are generated by the compiler, and can be obtained as implicits. With these you can hijack the java compiler and its type erasure.

The docs mention a less verbose but shorter version, instead of adding those implicit parameters, you can include them in the type parameter list like below.

It’s worth mentioning that ClassTags can only show you the erased class information, so you will know it’s a List, but you will not know whather it’s a List[String] or a List[Int]. If you want class matching this deep, you need to go deeper in the docs too (smile)

All in all: Java generics v.  Scala implicits

If you have never heard of the java type erasure, probably you are amazed by how could you use generics without this information, and if you as curious as I am you want to play with it a bit.

If you have never heard about the ClassTags, the above linked scala docs page could be a good read to see just how powerful and magical this tool can be.

If you already knew all the things above, you can maybe leave a comment with your suggestion as to how this can be more helpful to others (smile)

 

Gergő Törcsvári

Gergő Törcsvári

Software Developer at Wanari
I would love to change the world, but they won’t give me the source code (yet).