Generics Face-Off, Nugget #1

My last post was a bit overly enthusiastic about Scala. To counterbalance it, I present another “nugget” in this post, inspired by my slim experience on using Scala together with Java. You see, Scala aims to remedy some shortcomings of the Java typesystem, in particular its generics, which makes it somewhat uncomfortable, at times, to bridge the two. And the face-off you read in the title, will be between Scala and another JVM language, Kotlin, which aims more towards being a better Java than providing a wholly different solution. Let’s see how they do, using the scale used by Catch-22‘s Colonel Cathcart.

Java’s wacky use of Generics

Suppose there’s a generic Java class, named Something, presented here as a bare-bones example.

public class Something<T> {
    @Override
    public String toString() {
        return "Something";
    }
}

And here’s the rub. Java allows you to “cop out” of Generics and use either the erased type, or an existential type, in the following meaningless way (and I’m not making this up).

public class JTest {
    public static Something<?> getSomething() {
        return new Something<String>();
    }
}

Here’s some Scala code to process an instance of Something<String>.

class STest {
    def workWithSomethingString(s : Something[String]) {
        print(s)
    }
}

Suppose you know that the particular instance is a Something<String> (the way you know it lies certainly outside of the type system). Going from Java to Scala produces an unchecked warning, as it should.

    public static void scalaDriver() {
        STest sTest = new STest();
        sTest.workWithSomethingString((Something<String>)getSomething()); 
        //flagged as unckecked
    }

Enter Kotlin.

class KTest {
    fun workWithSomethingString(s:Something<String>) {
        print(s)
    }
}

Same thing here.

    public static void kotlinDriver() {
        KTest ktest = new KTest();
        ktest.workWithSomethingString((Something<String>) getSomething());
        //flagged as unckecked
    }

Both fail to cope with Java’s incongruent use of Generics. Hence, a black eye for both, in that regard. Hint: at the call site, it’s the Java compiler that runs the show. There’s really no way to win. Let’s see what we get if we give full control of the calling site to the other compilers.

Reified generics

If we disregard direct interconnection with Java, for a moment, both Scala and Kotlin want to provide some solution to being able to recover type information that is lost by erasure.

Scala does it using TypeTags and such, in various ways which employ the compiler to supply information about generic types from the calling site to the called method.

Below is one way to do it. The first call to workWithSomething delegates correctly to workWithSomethingString.

    def passTheBuck() {
        workWithSomething(new Something[String])
        workWithSomething(new Something[Int])
    }

    def workWithSomething[T](s : Something[T])(implicit t : TypeTag[T]) {
        if( t.tpe.typeConstructor =:= typeOf[String] ) {
            workWithSomethingString(s.asInstanceOf[Something[String]])
        } else {
            print("\nCannot handle\n")
        }
    }

How about Kotlin? Kotlin has promised reified generics, but it’s still in the roadmap. Black eye for Kotlin, feather in Scala’s cap.

Things don’t look so good for Kotlin, so far. In the next nugget, let’s see if it manages to recoup, using its distinguishing feature of mixed-site variance.

Advertisements

One thought on “Generics Face-Off, Nugget #1

  1. Pingback: HoSql Type System proof-of-concept | dsouflis

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s