News for hackers. Stuff that matters.
Re:Java Generics Are Turing Complete by kodfodrasz on Thursday May 26, 2016 @08:52AM (#11777503)
Too bad they are still pretty much useless in many cases because of type erasure, and many type constraints cannot be expressed (eg. constructor constraints)...

Still way better than no generics at all, but if you are used to better implementations these random limitations can be really painful..

Re:Java Generics Are Turing Complete by alimbada on Thursday May 26, 2016 @09:22AM (#11777678)
Don't know why this is being downvoted. I've been on a Java project for the last ~6 months after ~8 years of doing C#/.NET development. My brain hurts from seeing all the stupid workarounds in Java because it doesn't have real generics.
Re:Java Generics Are Turing Complete by the_af on Thursday May 26, 2016 @09:50AM (#11777908)
I guess it's one thing to claim Java generics have problems and another to claim they are "useless".

They are a big improvement over not having generics and, in my experience, one seldom sees those workarounds you mentioned. Sure, when they are necessary they are ugly... but how often are they needed in standard application code?

Re:Java Generics Are Turing Complete by kodfodrasz on Thursday May 26, 2016 @09:58AM (#11777966)
Last week wanted to use GSON in a generic method to deserialize to a type which is generic type parameter, in a method of the abstract base class. Unfortunately it could not be done without the implementations passing up their .class via super constructor.

IMHO deserializing JSON is quite a common application code.

If you are really interrested I'd create example code, but (as being lazy, and the mentioned code not being my property) I'd hope to take my word for granted :)

edit: I wrote useless in many cases!

Re:Java Generics Are Turing Complete by slantedview on Thursday May 26, 2016 @12:13PM (#11779107)
There are ways to resolve generics declared on base classes:

https://github.com/jhalterman/typetools

...but proper support of reified generics certainly would have been better.

Re:Java Generics Are Turing Complete by dpark on Thursday May 26, 2016 @10:53AM (#11778380)
> I guess it's one thing to claim Java generics have problems and another to claim they are "useless".

I guess that's why the original comment said useless in many cases. Not completely useless. The next sentence also said they are way better than no generics.

Re:Java Generics Are Turing Complete by brianbarker on Thursday May 26, 2016 @11:36AM (#11778745)
YES! to both parents here. Type erasure is a bitch.

Need to pass in a class type, but it's of a list?

List<YourType> list = new ArrayList<>(); yourfunc(list.getClass());

C# got all this junk right.

Re:Java Generics Are Turing Complete by benjiweber on Thursday May 26, 2016 @05:18PM (#11781719)
You can now use lambdas as generic type references http://benjiweber.co.uk/blog/2015/08/04/lambda-type-referenc...
Re:Java Generics Are Turing Complete by emodendroket on Thursday May 26, 2016 @09:51AM (#11777914)
What are the issues? I've never worked with Java enough to see them. I will say that reflection with generic types and methods in C# is a hassle.
Re:Java Generics Are Turing Complete by kodfodrasz on Thursday May 26, 2016 @10:05AM (#11778024)
In C# you can often avoid reflection using dynamic.

Java generics problems: "primitive types" cannot be used as type parameters. Type erasure makes type parameters unavailable at runtime, which sometimes causes many problems.

When you see java code passing a .class as a constructor/method parameter, that is often a workaround.

Try Stream.toArray(). Type erasure makes it a pain and forces you to provide an array Supplier.

Other Example: you cannot have overloads of a method one taking Function<T,U>, other taking Supplier<T> because their erased signatures are equivalent.

Disclaimer: I still prefer Java when C# is not an option, yet I reserve the right to criticize its shortcomings.

Re:Java Generics Are Turing Complete by vvanders on Thursday May 26, 2016 @11:07AM (#11778470)
Or even better, you can't use an array of generic types, which is just madness. Why even have a generic system if it's so half-baked.

Yes you can use ArrayList but you'd think that something as fundamental as an array would work with generics.

https://docs.oracle.com/javase/tutorial/java/generics/restri...

Re:Java Generics Are Turing Complete by oldmanjay on Thursday May 26, 2016 @11:37AM (#11778753)
I'm not sure if you articulated your overload beef correctly. What you wrote is trivially possible so charitably, you wrote it wrong.
Re:Java Generics Are Turing Complete by olavgg on Thursday May 26, 2016 @10:35AM (#11778240)
Could you not use Groovy for this? Using Groovy isn't harder than using another third-party library.
Re:Java Generics Are Turing Complete by kodfodrasz on Thursday May 26, 2016 @10:49AM (#11778347)
Yeah, if I wouldn't care for type safety, and I'd want to write validation code for stuff currently handled by GSON instead of me, by the class definitions.

We use Groovy for some things, but here I'd stick to Java.

Also Groovy has limited IDE support.

Re:Java Generics Are Turing Complete by vorg on Thursday May 26, 2016 @01:30PM (#11779841)
Apache Groovy's dynamic typing, closures, and shorthand collection syntax (from v. 1.0) are great for testing and playing with Java classes, and I'm told Groovy's Ruby-like MOP is useful for Grails developers, but the stuff added later (like generics in v. 1.5) made the language klunky and overdone. Best switch to Java (or Scala/Kotlin/etc) once you need anything to be typed, let alone with generics.
Re:Java Generics Are Turing Complete by bskap on Thursday May 26, 2016 @11:11AM (#11778510)
The most common annoyance is along these lines:

interface List<T> { T[] toArray(T[] item); }

You need to pass in a T[] because arrays keep their types at runtime but the generics don't.

Re:Java Generics Are Turing Complete by pif on Thursday May 26, 2016 @10:27AM (#11778171)
I worked several years with C++ and when starting C# I was astonished how much useful stuff C# generics are missing w.r.t C++ templates.

Now, I've never worked with Java, but if you say that java generics make you miss C# generics, they must be really horrible :-)

Re:Java Generics Are Turing Complete by clappski on Thursday May 26, 2016 @10:34AM (#11778233)
Out of curiosity, what would you say is missing? My one big beef with templates is lack of constraints and somewhat ugly syntax, but hopefully concepts will remedy the former.
Re:Java Generics Are Turing Complete by pif on Thursday May 26, 2016 @10:53AM (#11778379)
My one big beef with generics is that they only work through constraints! With templates, the compiler checks the validity of a template only when applying it to a concrete type; a generic, OTOH, needs to be valid as an independent entity. And this means that you are stuck with the limitations of the constraints: you cannot specify that your type has a constructor accepting parameters, you cannot specify static methods, nor operators.

With generics, you can only pass complete types as generic parameters; templates accepts types, templates and integral constants.

You can't have partial specializations with templates.

Typedef. This is the most annoying limitation I found in C#. You cannot type:

  typedef vector<MyClass> MyList;
and have it valid in the whole project.
Re:Java Generics Are Turing Complete by xenadu02 on Thursday May 26, 2016 @12:53PM (#11779479)
That's not inherent to generics - see Swift, which absolutely allows protocols to require static/class members or initializers. Swift 3 also adds generic type aliases (typedefs).

Having worked extensively with both I think Swift learned a lot from C# (and many other languages).

As for Concepts... No one seems to be able to agree on them so I'm not holding my breath.

Re:Java Generics Are Turing Complete by tomp on Thursday May 26, 2016 @10:38AM (#11778262)
What exactly is missing, or better in C#? I'm surprised because I've been programming in OCaml for a long time, and never missed "real" (i.e. non-erased) generics.
Re:Java Generics Are Turing Complete by barrkel on Thursday May 26, 2016 @12:12PM (#11779102)
Unboxed values; this primarily affects performance, particularly memory performance, but with a sufficiently smart compiler could be worked around. It's unlikely any very clever JVM optimizations would see wins here though, as the assumption that everything is boxed is idiomatic.

Having a type argument available; as adevine mentions, performing type-level things rather than just instance-level things. A smarter language than Java could handle this with hidden arguments, or passing along a dispatch table for type-specific actions when constructing a generic type. Things get trickier when you're e.g. storing a reference to a static generic method.

In reality, there's a continuum between C++-style generics-as-parameterized-syntax-trees and Java's generics-as-ignorable-type-checker-façade. Going full C++ isn't what you want; the error messages on failure to instantiate are unpleasant. Going full Java leaves you with a few holes. C# is probably a small bit too far in the C++ direction - instantiations can add up, despite .NET reusing instantiations where the type arguments are object references (that is, the CLR will effectively erase types if your type arguments are reference types, but you can't observe this without escaping the type system).

Re:Java Generics Are Turing Complete by adevine on Thursday May 26, 2016 @11:24AM (#11778620)
For me, it's mainly that you know the runtime type of the type parameter, so you can do things like new T() in your generic class.
Re:Java Generics Are Turing Complete by kmiroslav on Thursday May 26, 2016 @03:15PM (#11780692)
Pass a factory `createT()` instead, problem solved.
Re:Java Generics Are Turing Complete by adevine on Thursday May 26, 2016 @03:40PM (#11780866)
Exactly - except it's gross and results in a lot of annoying boilerplate code for what should be considered a simple operation.

Tons of generic APIs essentially do the same thing by passing in the class object in the constructor, e.g. http://stackoverflow.com/a/1090488/1075909 . The question for people not that familiar with the Java type system is often "Why do I have to pass in the class object when I just declared the type parameter in my instance?"

That's not the only thing you need to workaround because of type erasure (the "TypeToken" stuff in a lot of deserialization libraries is another one that comes to mind frequently), but it's probably the first annoying example people hit.

Re:Java Generics Are Turing Complete by kmiroslav on Friday May 27, 2016 @10:17AM (#11786187)
Erasure is not the problem here, you need to be able to specify a type constraint that will allow you to invoke T(). What if T is an interface? An abstract class? A class with no default constructor?

The only reasonable way to do this is to accept a lambda that tells the compiler exactly what call is legal to create an instance of T.

And that's called a factory.

Re:Java Generics Are Turing Complete by adevine on Friday May 27, 2016 @05:39PM (#11789235)
Yes, good point. But if you did have a type constraint, like C#, you would still need the runtime type info to know what to create. This is legal in C#:

public static T Factory<T>() where T:new() { return new T(); }

Re:Java Generics Are Turing Complete by scott_s on Thursday May 26, 2016 @11:33AM (#11778714)
I downvoted it because it is not relevant to the submitted article. I would rather see discussion on the actual result - Java generics are not decidable. A discussion on whether or not Java generics are good is, in comparison, boring.
Re:Java Generics Are Turing Complete by cel1ne on Thursday May 26, 2016 @09:33AM (#11777747)
Kotlin, which is 100% java-interoperable has much nicer generics (declaration-site variance and type projections instead of wildcards).

https://kotlinlang.org/docs/reference/generics.html

Re:Java Generics Are Turing Complete by rsmckinney on Thursday May 26, 2016 @03:11PM (#11780661)
Take a look at Gosu. It provides:

  - Reification
  - Declaration-site generics
  - Default covariance when variance not specified
  - Variance inference!
In practice default covariance is usually the most suitable; it's the pragmatic approach. But you can make a generic type super sound, if that's what you need. And with variance inference your generic type can safely inherit from generic Java types.

http://gosu-lang.github.io/2015/11/22/threading-the-needle.h...

Re:Java Generics Are Turing Complete by pekk on Thursday May 26, 2016 @04:14PM (#11781136)
Is there a reason to take a look at Gosu instead of Kotlin?
Re:Java Generics Are Turing Complete by rsmckinney on Thursday May 26, 2016 @04:23PM (#11781220)
You mean aside from it providing better and easier generics support? I personally like Kotlin, but I think Gosu has some advantages that should not be overlooked e.g,. Generics support.
Re:Java Generics Are Turing Complete by oweiler on Saturday May 28, 2016 @12:50PM (#11792313)
The problem with Gosu is that it never gained any significant traction.
Re:Java Generics Are Turing Complete by kailuowang on Thursday May 26, 2016 @11:02AM (#11778444)
I actually think type erasure might even be the right way to implement generics. You see, the point of static types is to provide compilation time check. That is, types are compilation time concern. So yeah, type erasure did introduce some inconvenience but if you need to access them during runtime, either you did it wrong or the compiler fails at some point.

So, claiming type erasure making generic useless is a false argument.

Re:Java Generics Are Turing Complete by gpderetta on Thursday May 26, 2016 @02:12PM (#11780212)
I think that the problem with Java is not that they are implemented with type erasure (many functional languages do the same and monomorphize only when optimizing), the issue is that this implementation detail is a leaky abstraction in Java.
Re:Java Generics Are Turing Complete by MereInterest on Thursday May 26, 2016 @11:04PM (#11783620)
Type erasure also makes some forms of function overloading impossible.

    void func(List<ClassA> list);
    void func(List<ClassB> list);
Using type erasure, I cannot specify functions that are overloaded based on the generic type of an argument. To the runtime, both of these accept an argument of type List<Object>, and so it is ambiguous which one to call.

In C++, which does not use type erasure, this sort of function overloading works as expected.

Re:Java Generics Are Turing Complete by kodablah on Thursday May 26, 2016 @02:00PM (#11780124)
Not to mention, having type erasure made them backwards compatible with non-generic implementations. I don't think it would have been acceptable to break old Java code or introduce an entirely new collections library like .Net did.
Re:Java Generics Are Turing Complete by eternalban on Thursday May 26, 2016 @01:22PM (#11779762)
Pretty sure the scope of the generic stage is the compilation unit.
Re:Java Generics Are Turing Complete by vvanders on Thursday May 26, 2016 @10:10AM (#11778061)
Or my personal favorite where intrinsic types aren't objects so I can't use them in generics with makes the whole Lambda/Stream api a complete disaster.

Sure, I could use Integer/etc, but now each stage of my transform is creating a ton of garbage and I no longer get data locality.

Re:Java Generics Are Turing Complete by aardvark179 on Thursday May 26, 2016 @10:15AM (#11778091)
Keep an eye on project Valhalla.
Re:Java Generics Are Turing Complete by bad_user on Thursday May 26, 2016 @04:00PM (#11781006)
You don't need reified generics with a more powerful type system. You might be feeling that C# .NET is better than Java, but it's actually a symptom that C#'s type-system also sucks. Basically whenever you have to do an `instanceof` check, that's a sign that the type system isn't strong enough and hence needs to be solved at runtime.

One such thing missing from .NET for example are higher-kinded types. Basically people end up with the need for `instanceOf` because they aren't able to write generic code that abstracts over containers such as List[T].

And this holds back language development on top of .NET actually. There are good reasons for why alternative languages flourished on top of the JVM and not on top of .NET, in spite of its original marketing, which is a little ironic. Not the only reason mind you, other reasons where availability on Linux, having an easier time to generate bytecode along with debugging symbols, more mature tooling, etc, but having reified generics in the runtime either means that you have to limit your language (e.g. C#'s type-system with a different syntax), or it means that you have to do the type erasure yourself and always have performance problems and be considered a second class citizen. Lack of higher-kinded types is actually what's holding F# back as an FP language, because in FP there is a lot of opportunity to abstract over M[T] types, that are just not doable in a static language without HKT.

And don't get me wrong, I like dynamic typing as well, but the problem with languages like Java and C# are that they are neither here, nor there, in many ways being the worst of both worlds.

And the only advantage that .NET's reified generics have over Java is actually the specialization it is doing for primitives. Which is nice for performance reasons, since you avoid boxing and so on, but doing specialization doesn't necessarily need to be a runtime feature, when it can very well be a feature of the language's compiler. And we weren't talking about performance anyway.

Re:Java Generics Are Turing Complete by galdosdi on Thursday May 26, 2016 @10:59AM (#11778414)
Eh, there are hacks around both of those... Gratuitous "typedef classes" for the first problem (instead of using a List<Sandwich> when you want runtime to be able to sniff the type, declare a class/interface SandwichList extends List<Sandwich> and use that) and just wrapping static factory methods around constructors to handle the generic part (to handle the second problem)

Admittedly this is a little annoying, possibly even "really painful" so this doesn't really contradict your view... I don't find it really painful, just a little annoying, but that could be because I haven't used C# or another language people say has better generics so I don't know what I'm missing...

Re:Java Generics Are Turing Complete by curried_haskell on Thursday May 26, 2016 @10:33AM (#11778224)
After spending several years programming with Scala and Haskell, doing back to Java feels like being placed in a straightjacket.
Re:Java Generics Are Turing Complete by acjohnson55 on Thursday May 26, 2016 @03:49PM (#11780919)
Java generics are cumbersome for sure, but if they're useless, it's not because of type erasure. As a Scala programmer, I've very rarely run into a situation where type-erasure has been an inconvenience.
Re:Java Generics Are Turing Complete by joegaudet on Thursday May 26, 2016 @02:02PM (#11780140)
Re:Java Generics Are Turing Complete by bitmapbrother on Thursday May 26, 2016 @02:32PM (#11780376)
If it weren't for type erasure we wouldn't have the abundance of dynamic languages on the JVM. Developing dynamic languages on runtimes that have reified generics is a PIA.
Re:Java Generics Are Turing Complete by WorldMaker on Thursday May 26, 2016 @03:42PM (#11780879)
IronPython, IronRuby, and plenty more dynamic languages on the CLR which has reified generics certainly disagree with your opinion here.

If anything, my opinion is that the abundance of so many dynamic languages on the JVM, and the active use of those dynamic languages in JVM projects, has much more to do with how no one really wants to work in Java than anything to do with how generics work (or don't work) in the JVM.