views:

538

answers:

3

I'm just wondering about an implementation detail of sScala generics. In C# one can declare a class as:

class Foo<T1>{}
class Foo<T1, T2>{}

In Scala however the same thing would have to be declared as

class Foo0[T1]{}
class Foo1[T1, T2]{}

Notice how the class name is forced to be changed for multiple generic parameters. Is there a reason that Scala decided to go this route rather than the C# one which I feel is more elegant? I know this is probably a pretty small nitpick, but I'm pretty curious as to the reasoning.

+2  A: 

It may well be partly due to Java's similar restrictions. As I understand it, Scala is mostly used on the JVM, where you can't overload generic types by arity.

It looks like Scala uses type erasure for its generics too, even in the .NET port. (The same article mentions that Scala had generics long before Java really did, so even if Java did support this, there's no guarantee that Scala would - they were somewhat restricted when they first designed the feature.)

Jon Skeet
Wasn't type erasure just a clever (more or less) hack to avoid chages to the JVM? If so, wouldn't Scala require the very same changes to the JVM to support generics at runtime? I'd rather think Scala is not much better off than Java in that regard.
Joey
It would unless it added some type information into each instance as a hidden field, or something like that. It's certainly very difficult to add something like "proper" generics to a runtime that doesn't support them.
Jon Skeet
Note that Scala generics can be higher kind, unlike .NET's. I don't see how to add them into .NET without erasure.
Alexey Romanov
@alexey_r: Fair enough - I don't know enough Scala to know. Would it be possible to use erasure where necessary for higher kind generics, but no erasure for "simple" generics?
Jon Skeet
You certainly COULD create a language that overloaded based on type parameter arity on the JVM by inventing your own class name mangling scheme (very similar to how C++ overloads on function/method type and arity). But that would negate once important area of Java integration.Also, I don't see how erasure is "improper" given that most implementations of ML derivatives and Haskell erase all types at runtime.
James Iry
Okay, maybe "proper" was an unfortunate word - but I'll say that in my experience of Java and C#, I *frequently* find it irritating in Java and find C# a blessed relief on this front. (On the other hand, Java's caller-side-variance can be useful, if complicated.) It's also quite possible that C# developers are going to use generics differently to Haskell developers, just as many Haskell developers probably wouldn't count .NET delegates as "proper" function types, for example.
Jon Skeet
+2  A: 

I suppose it is done for easier mapping to Java, which has the same restriction.

It would have been possible to do some name mangling, but at the price of making interoperation with Java more difficult. In my view they took the right decision.

starblue
+11  A: 

I know Jon Skeet's answer has been accepted, but it's not quite right. It's not so much the JVM that forces a limitation as it is the Java language. Scala has a design goal of being as easily callable from Java as possible and Java has no concept of overloading a class name based on type parameter arity. For instance, a simple way to implement overloading based on type parameters on the JVM would be with name mangling. However that name mangling would have to be visible to Java and would be ugly. In your example, a hypothetical Scala might compile two classes, Foo_$1 and Foo_$2. Scala could make that mangling invisible. However, a Java programmer would see all that ugliness.

James Iry
I'm pretty sure this is what C# does anyway. Foo<T>'s type name would be Foo`1.