Generics over values. It is persistent irritant that generics do not work over primitive types today. With value types, this irritation will increase dramatically; not being able to describe List<Point> would be even worse. Still worse would be having it mean “today’s list, containing boxed points”. Supporting generics over primitives and values, through specialization, is the topic of a separate investigation.
The need for boxing/unboxing is for me one of the most common sources of facepalm in Java. I guess it's difficult to fix without breaking existing code (I guess that a new implementation of generics may not break java code, but it would break existing bytecode), but it's really annoying.
Note that specialization ("templates") are not a JVM issue but a language issue. If the JVM offers value types, then any JVM language can choose to provide specialization -- or not. In fact, this might be a better idea than baking specialization into the JVM (as done in .Net), as doing so might enforce a specific implementation of generic types, and might prevent other JVM languages from providing their own, novel type systems.
Java needs feature opt-in, import future.sane.Generics; and so on. (Scala has these.)
Python learned it the hard way. The value of backward compatibility got a bit underestimated there, with Java it's going the other way (the value of progressing, giving better tools to developers is overlooked). The JVM is a big bag of crazy code already (HotSpot with C1 and C2 JIT compilers, the many garbage collector algorithms/implementations and the other stuff that is currently deemed the JVM's responsibility), so there's plenty of space for new opt-in features.
Feature opt-in sounds good. The C++ people did it. Look what happened. Qt, boost, gtkmm, mscf are all (more or less) good. But you can't (shouldn't) mix them.
Basically. If you want to implement generics you basically have the choice of 1) boxing (Java approach), 2) instantiating a different type for each generic parameter (C++ approach), and 3) doing something in the runtime to enable a relatively transparent hybrid (C# approach). They each have their own tradeoffs in terms of flexibility, memory consumption, runtime complexity, and compilation / linking time.
This functionality is old and because it tends to generate many class files, there's also a newer project that fixes that and that should replace the @specialized annotation soon: http://scala-miniboxing.org/
"The Java Hotspot Server Compiler implements the flow-insensitive escape analysis algorithm."
This is actually a big problem. The key word is "flow-insensitive". Because current JVM escape analysis is flow-insensitive, it misses lots of opportunities.
Thankfully, this is changing. Oracle recently published "Partial Escape Analysis" paper http://dl.acm.org/citation.cfm?id=2544157 and I hope it will be integrated in future versions of JVM.
Feels like it needs proper (reified/runtime) generics in order to be useful. Reified generics and value types would be a complete and long overdue break in backwards compatibility.
But
It's a bit sad how java struggles to become a C# from five years ago. Would make a lot more sense to leave java alone, add reified generics and value types at the bytecode/vm level and instead launch a new language that could use all of it.
Throw in pattern matching, algebraic data types and a bit more and I'm sold.
> Feels like it needs proper (reified/runtime) generics in order to be useful.
Actually type-erasure is one of Java's best features, because it didn't cripple the runtime for other languages. For example Scala's type system is too expressive to be built on top of .NET's generics.
First of all, reification only helps in terms of type-safety if you have a weak type system. The only value that reification, as implemented in .NET brings is specialization for value types.
Second of all, specialization can be done by the compiler. That's how many languages have always done it. Scala for example has a @specialized annotation for specializing type parameters for primitives [1]. And because this functionality has some gotchas, there's also an up&coming project plugin that's meant to be a replacement in future versions of Scala and that works really well [2]
I myself have used the @specialized annotation on many occasions and in general it does what it's supposed to do. And if that means I can develop in languages like Scala, Clojure and JRuby on top of the JVM, then I really, really love type-erasure. And oh, apparently one barrier for implementing type-classes in F# are the generics in .NET ;-)
> It's a bit sad how java struggles to become a C# from five years ago
What I find sad is grown men that can't see the forest from the trees. Java, the language, is totally irrelevant and uninteresting and I like it that way, because it's the kind of language you can rely on in case you want backwards-compatibility (yes, that's a feature). On the other hand, the JVM is light-years ahead of the CLR, because that's what the Sun, now Oracle engineers have been doing with all of their time.
> pattern matching, algebraic data types
See Scala. It also does type-classes and higher-kinded types, amongst others that F# is not capable of.
Actually type-erasure is one of Java's best features, because it didn't cripple the runtime for other languages. For example Scala's type system is too expressive to be built on top of .NET's generics.
...
People keep repeating this stuff and they're totally wrong. F* is dependently typed and is a CLR language.
bad_user, have you ever actually attempted to write a type unsoundness proof for your claim or are you just repeating something you heard somewhere?
There is nothing stopping a language implementer from ignoring CLR generics and leveraging erasure to do their own thing. The problem is that such a language is basically cut off from providing a bridge interface to any CLR library that uses generics. I would guess this is why many core Microsoft libraries (say WPF) don't use generics even though they could (but it could just as much be that they were started before generics were pervasive in C#).
The LAMP team actually got pretty far with Scala on the CLR. The reason it didn't go farther was more due to a lack of interesting and funding.
Yup, I mentioned this in a comment below -- interop is always the problem. Then again, anyone who has looked under the hood and seen just how much MS stuff is based on COM knows all about that.
This is so that F# could have higher-order types and interop them with other .NET languages. F#'s type system is simple partly because it strives to use the existing CLR type system, limitations and all.
If you have no such requirements (e.g., Scala, where there's no requirement that Java be able to consume or interpret all of Scala's types), then you can most definitely define a language for the CLR which does this.
F* is not a typo -- that is not F#, it is a separate language.
I am very interested in F*, I heard about it and I'm waiting eagerly for something polished.
Personally I don't like F#, the result, because on one hand you've got the Hindley-Milner type system and on the other hand you've got OOP with .NET generics. It resembles Ocaml in philosophy (I'm sure this wasn't by accident), in that it feels and smells like 2 type-systems in the same language. It's just an opinion of taste of course - but would have anybody used F# if it didn't integrate well with .NET's standard assemblies? So F#'s integration with .NET's generics is very understandable and one reason Scala.NET died was because it was too hard to keep the semantics of Scala, while also integrating well with .NET, which meant the project was interesting only for people wanting to port their Scala code to .NET - for which approaches like IKVM.NET were far better options. I think somebody wrote an interesting paper on Scala and .NET's reified generics, sadly I can't find it right now.
You may have gotten annoyed about hearing this thing about .NET generics not being expressive enough - I also get annoyed hearing about how Java sucks because it doesn't have reification for generics or other such things, when in truth the compiler can handle specialization just fine and both approaches (runtime versus compile-time) have merit and make different compromises.
BTW, I see that you're working on the Roslyn team - you guys are doing great work lately. Keep it up.
I happen to agree with you -- I think the technical limitations in both languages/VMs are highly overrated. Java, especially, has been a victim mostly of insufficient leadership and resources, not any fundamental technical issue.
C/F# and the CLR, meanwhile, are probably most limited by backward compatibility.
I'm not saying erasure is a bad idea for the jvm, but from a java perspective it's horrible. Not having structs or primitive/struct collections makes all types of low level interop and/or high perf (e.g game) programming cumbersome.
Specialization for value types (including ones not known at compile time) is the main point imho of reified generics, yes.
I like scala and agree that F#'s typed sometimes feels like the bastard child of ML and C# (although I do like ML syntax better).
I agree with you that the backwards compatibility of java is a feature now, since so many other languages incorporate what we'd otherwise want to see in java.
I thought that compile time specializations wouldn't reach all the way, just like C++ templates don't.
You can use java jars with the -java-lib flag. The whole library ecosystem is available. There's not as much IDE tooling for Haxe, but Haxe is a lot more succinct. I haven't needed that as much.
I'm excited about this not because I'd use them in Java, but because JVM support for value types could make the case classes I'm using in Scala much more efficient.
That depends. Value types don't support polymorphism and subclassing. More specifically, you can't have an array of a union value type like you would in C. Could case classes do without polymorphism?
Case classes as they currently stand cannot do without polymorphism. That said the Scala team doesn't show a lot of hesitancy in adding new features so I wouldn't be surprised if they implemented case value classes of some sort once the JVM supports them natively.
How will the exiting libraries handle that? Would they be able to store the whole "value objects" instead of just pointers to them?
That being said, not being Java programmer, I'd like to know what's the state of the libraries now? Do libraries handle the collections of the primitive types and the collections of the objects differently now, using the most efficient infrastructure, or is it something that you have to select as the programmer manually even now on case-by-case basis?
> Do libraries handle the collections of the primitive types and the collections of the objects differently now
You can't use the built in collection classes on unboxed primatives, but there are a few different popular third party libraries that help overcome that. For example, Google guava has utility classes to work with arrays of primitives as if they were lists (https://code.google.com/p/guava-libraries/wiki/PrimitivesExp...). There's also GNU trove, and Goldman Sachs' java library. Maybe somewhere in the apache commons library too, I don't remember.
I think the reality is that the vast majority of programmers don't find themselves in situations where the boxing of values causes obvious performance penalties. At least, not at the scale that shows up.
So, in general, most libraries just ignore collections of primitive types.
I think you're dealing with an selling ice cream in winter problem here. There's a significant number of programmers who need this behaviour, but you don't hear from them because they have no interest in Java, because it doesn't even have rudimentary support for their use cases.
It is hugely significant when doing 3D coding if you want to use the convenience of vector and matrix types (and you really do because doing operations on raw floats it not scalable and it is bug prone.)
Background: I did a lot of 3D app dev in Java in the 1998-2001 time frame and then switched over to C#. C# was a huge improvement because it had value types. When you have 5M vectors, you really do not want each to be its own allocation.
Oh, I did not mean to imply it is not a huge factor where it matters. Probably makes a bigger difference in standard CRUD fair apps than people realize.
My assertion is simply that compared to the cost of serializing to/from database/user, it is probably not the pain point of many programmers. Hence, most programmers probably don't think about it.
Just ask a few developers about the ridiculous overhead of HashSet<Integer>. And then see how many places people still use it.
The problem is that the reason people need value types is often for performance - once you've busted out value types for performance, you expect to be able to keep it with generics, and that's where boxing/unboxing becomes apparent.
Unboxing can also produce counter-intuitive typecast behavior.
If I want to cast an object-boxed int into a short
Object myBoxedInt = GetInt();
short myShort = (short)(int)myIntObj;
because casting directly to short is a run-time exception. I've run into this problem in C#, but my understanding is that Java shares it.
Hmm.... good point. I would assume that would be a different initiative. Though, my initial thought of "value types" getting boxed doesn't really make sense. What would they even be boxed as?
"Wrapping. Just as the eight primitive types have wrapper types that extend Object, value types should always have both an unboxed and a boxed representation. The unboxed representation should be used where practical; the boxed representation may be required for interoperability with APIs that require reference types. Unlike the existing primitive wrappers, the boxed representation should be automatically generated from the description of the value type."
So there is some boxing planned. What does it mean for the programmers, the users of existing libraries? Ah, I believe gordaco hints to that in his comment.
Also perhaps interesting for comparison, a 1981 Lisp Machine library called DEFSTORAGE provides structures on memory, based on a similar feature of PL/1. For example used in the Lisp Machine file system. Example from Symbolics Genera:
(defstorage (file-header)
(version fixnum)
(logical-size fixnum-bytes 2)
(bootload-generation fixnum) ;for validating
(version-in-bootload fixnum) ;used in above
(number-of-elements fixnum-bytes 2) ;for later expansion
(ignore mod word)
(* union
(parts-array array 8 fh-element)
(parts being fh-element ;and/or reformatting
fh-header ;this header itself
info ;header-resident info
header-fm ;file map of header
dire ;directory-entry-info
property-list
file-map
pad-area ;many natures of obsolescence
pad2-area)))
Very interesting. Would possibly improve the performance of some programs, as iterating over an array of value types will actually be sequential memory access, whereas iterating over an array of objects involves skipping everywhere over memory.
It's definitely encouraging. I don't know what the current state of the art is, but one of the main conclusions of the NIST Java Grande working group back in 2000-2003ish was that lack of a complex type was one of the big things holding Java back for numerical work.
There was a wave of excitement about doing numerics in Java around 2000ish, but it seems like everyone has since moved on.
Not quite. Unlike C# structs, this is not a memory-layout choice, but a semantic choice. Value types have specific semantics: immutable, atomic, non-extendable etc. It is up to the VM to choose how to lay them out in memory, but an on-stack/inlined-in-array storage would be possible.
The linked article's title is "Value Types for Java". If you want to add some context to the article, as you presumably do by posting it with the title "Initial proposal for Java value types made public", can you do that by posting a comment? For example, your title makes me wonder:
* Has the proposal progressed beyond this 'initial' version?
* What were the circumstances that led to it not being public originally?
* What circumstances have led to it having been made public now?
The point is that the proposal now is pretty much identical with what Scala people wanted in the first place.
The single-field restriction is there because there are limits in how aggressive one can fight a non-cooperating runtime, not because it was their principled choice.
Possibly missing something here but couldn't the 'value type' distinction be made with an annotation? I think that would be cleaner and possibly more flexible as well.
Probably, (also makes back compatibility to earlier jvms easier). However, I think the authors went for "horrible syntax in examples" so that we have time to think about a final good/decent syntax. See what happened with lambas lots of proposed syntaxes ended up with one decent one.
Here they want a discussion by implementers about the technical side and avoid bikeshedding about syntax (for now).
Indeed it could be, but that's syntax. The proposal is very careful to talk about semantics; most of the code examples have a disclaimer that the syntax is for illustrative purposes only.
MAKE VALUE TYPES EASIER TO USE AND EXPLOIT THE TYPE INFERENCE CAPABILITIES
Hi! I have some ideas that I think They would be interesting on how to use Values Types. I have two proposal: How to define if? and how to use it? The two are separate proposal. I will write the first proposal.
1.Defining Value Types?
A. What about forcing a primary constructor to indicate that it is a value type, there is some thing like it in C#6, but in C# it just to make easy to define a primary constructor. So in Java we can use it differently. So we can say that if we use it that we are defining a value type. It is possible to have more than one explicit constructor. But I don't think that we have to force developer to write a constructor if it is not necessary. Why? According to the document Value-types constructors are really factory methods, so there is no new;dup;init dance in the bytecodes.
So I think that to define a value type we can only do:
<p><pre><code>
final class Point(int x, int y){
}; </code></pre></p>
x and y are automatically final and public members. So that can exactly be compiled like:
<p><pre><code>
final __ByValue class Point {
public final int x;
public final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public boolean equals(Point that) {
return this.x == that.x && this.y == that.y;
}
}
</code></pre></p>
Simple, concise and contributes to productivity. I also I thought about something new.
We can also do:
<p><pre><code>
final class Point(int x, int y){
private int c;//if I wont
boolean equals(Point p){
return this.x==p.x&&this.y==p.y}
public static Point getFunPoint(){
}
public static void maFunction(Point p, boolean b, double b){
}
}
</code></pre></p>
B. Why not an implicit default equals. So if I do :
<p><pre><code>
final class Point(int x, int y){}
</code></pre></p>
that means if the JVM doesn't find an explicit equals, it cans do logical compare.
<p><pre><code>
public boolean equals(Point that) {
return this.x == that.x && this.y == that.y;
}.
</code></pre></p>
So a Point can be defined in one line:
<p><pre><code>
final class Point(int x, int y){}
</code></pre></p>
C. If we don't want to define something else in a value type, braces can be optional as in lambda expressions :)
So to define a value type we can only do:
<p><pre><code>
final class Point(int x, int y);
</code></pre></p>
No, they did mean, "like an int." in that value types in java are intended to be atomic and immutable in the same way primitives types already are and that structs (in many languages) aren't.
It is not. Java dinamic as runtime (if that means something) but is statically typed. Java is dinamic in some ways, arrays have not declared size, has reflection and dinamic method dispatch, but all clasess and are declared and required.
A final class can be represented as a simple (plain) struct if the scape analysis tells so, and allocated on the stack. Else, that inmutable object can be used as a lock, inserted into a collection (think hash) or whatever you can do with an object.
Only 14 years after it introduced with version 1.0 of C#. Java moves really slowly these days. Java lost a lot of credibility in the 3D visualization market in part because it is crazy inefficient to do 3D without value types. C# did very well there with the XNA tool did in part because it had value types and Java didn't.
I wouldn't have moved from Java to C# for desktop apps back in 2001 if Java had stated they would have adopted value types quickly, but they didn't.
History has moved on though and Java isn't really used for desktop apps at all now so this is a moot point. (And C# is on its last legs as well as a desktop development tool, except in large organizations...)
Downvoted to -1 for stating a fact. That has never happened before. Edit again, seems I've been upvoted again. Rollercoaster ride today.
Besides being mostly off-topic (not entirely, since it does talk about value types), this comment is arguably a middlebrow dismissal, since it dissmises a serious piece of work without engaging anything interesting in it, and for a superficial reason.
That reason (Java moves slowly) may be valid or may not be, but it isn't interesting in the HN sense of the word, because the route from the article to there is entirely predictable. Such comments get upvoted because they elicit the pleasure of recognition ("I've noticed Java moves slowly too!" or worse, "Yeah, Java sucks!"), and that is a reflex reaction, not a thoughtful one. We all do it—but if we're to have reflective discussions instead of reflexive ones, we need to inhibit it.
The larger problem here, though, is the dreadful subthread the comment spawned. HN threads are sensitive to initial conditions, and middlebrow dismissals lead to lowbrow rejoinders. It's the online comments equivalent of "B players hire C players".
All: please re-read what you're posting and reflect on it. If it goes on a tangent, make sure that tangent is not a predictable one. But if there aren't many comments in the thread, try not to go on a tangent at all—sensitivity to initial conditions means it may well derail the discussion.
I do want to point out that bhouston does have a nugget of useful insight in his post: Java lost a lot of credibility in the 3D visualization market in part because it is crazy inefficient to do 3D without value types. C# did very well there with the XNA tool did in part because it had value types and Java didn’t.
That's a very interesting point: the lack of this very feature closed Java off from an entire field. That implies that if this feature is implemented, it could open up that field to Java. (And, presumably, others with similar requirements.) I wish that bhouston had expanded on that subject.
This, I think, can make the difference between a middlebrow dismissal and an insightful contribution. Instead of framing a comment in terms of what is wrong, frame it in terms of "what would this enable"? You can still make the same fundamental points ("Java lost 3D visualization because it lacked this feature"), but the ensuing discussion can be very different. The post changes from a dismissal to the start of a discussion.
I've played around with it. It doesn't seem like a huge perf boost and would require a lot of dev work -- people who want value semantics use value types and the CLR can do better analysis then we can (e.g., across assemblies).
I think on the JVM's escape analysis was originally introduced to get rid of intrinsic locks, a task it does really well - something which I can say after countless of benchmarks I made trying out different synchronization strategies. Currently it's really hard to beat the JVM's intrinsic locks (i.e. the synchronized block), precisely because of this - because if the JVM detects that some piece of code is single-threaded, then it eliminates the lock completely.
I think stack-allocated values by means of escape analysis done at runtime is just an extension of that.
Also, escape analysis, theoretically at least, goes beyond what one can do with value types. For instance functional/persistent data-structures are guilty of generating a lot of short-term junk and because internally these data-structures are represented as trees, you need references for linking the nodes together. On the whole I am pleased with how well the JVM handles short term junk, whether escape analysis plays a part in it I don't know.
We went back to C++ because C# just isn't supported on Linux well, and Windows is losing its once dominant position. If C# worked on iOS and Linux equivalently to Windows, then I probably would have stuck with it.
But now I do JavaScript + WebGL (which is admittedly slower than both C#, Java and C++): http://clara.io
https://xamarin.com/ imho a much better alternative to C++. I really like C# as a language, it's got that general purpose excellence, but when you get on with things like LINQ,Rx,TPL it's very hard to go back to a language without such first class citizen frameworks.
It probably depends on the market and use case. I suspect LOB software is mostly web based these days (easier to deploy, upgrade, and maintain). A lot of desktop software is still written in C/C++ for Win32. Although Microsoft would probably love it if developers starting coding to WinRT which, I think, works best with C#.
Maybe you were downvoted for leaving a comment that had fuck-all to do with the topic? Maybe people just don't want to go in for yet another round of Java bashing?
Large orgs developing apps for internal use are pretty much the only people doing non-game desktop apps these days. They're still happy with it as an inheritor of Visual Basic, and if you're happy to be Windows-only it works very well.
I agree that Microsoft abandoning XNA development was a very disappointing decision, it was a pretty good tool.
Does anyone else find the syntax choices for many of the new Java features to be really distasteful? As a sacrifice to the gods of backwards compatibility, Java syntax seems to going the way of C++.
They say that it's a strawman syntax, i.e. it's an intentionally terrible syntax that isn't meant to be used for real to get people to focus on the concept instead of bikeshedding syntax.
Generics over values. It is persistent irritant that generics do not work over primitive types today. With value types, this irritation will increase dramatically; not being able to describe List<Point> would be even worse. Still worse would be having it mean “today’s list, containing boxed points”. Supporting generics over primitives and values, through specialization, is the topic of a separate investigation.
The need for boxing/unboxing is for me one of the most common sources of facepalm in Java. I guess it's difficult to fix without breaking existing code (I guess that a new implementation of generics may not break java code, but it would break existing bytecode), but it's really annoying.