diamond operator

R

Roedy Green

I was looking over the table of contents of a book about new features
in Java 7 and came across a reference to the "diamond operator".

It turns out to be simple, but one of the precious bits of Java
syntactic sugar to make it terser.

http://fahdshariff.blogspot.ca/2011/07/java-7-diamond-operator.html

http://mindprod.com/book/9781849685627.html
--
Roedy Green Canadian Mind Products
http://mindprod.com
When you were a child, if you did your own experiment
to see if it was better to put to cocoa into your cup first
or the hot milk first, then you likely have the programmer gene..
 
A

Arne Vajhøj

I was looking over the table of contents of a book about new features
in Java 7 and came across a reference to the "diamond operator".

It turns out to be simple, but one of the precious bits of Java
syntactic sugar to make it terser.

http://fahdshariff.blogspot.ca/2011/07/java-7-diamond-operator.html

It is listed in the release notes:
http://www.oracle.com/technetwork/java/javase/jdk7-relnotes-418459.html
that link to the docs:

http://docs.oracle.com/javase/7/doc...type-inference-generic-instance-creation.html

It was probably also discussed here last summer when
Java 7 was released.

Arne
 
D

David Lamb

With some exaggeration one might call it Java's type inferencing...

Well, maybe, but from the little I recall of my programming language
design classes, "real" type inferencing is a lot more powerful, so I
think you ought to have said "much exaggeration."
 
S

Silvio Bierman

Well, maybe, but from the little I recall of my programming language
design classes, "real" type inferencing is a lot more powerful, so I
think you ought to have said "much exaggeration."

Yep, it was an understatement.
 
J

Jim Janney

A

Arne Vajhøj

Well, maybe, but from the little I recall of my programming language
design classes, "real" type inferencing is a lot more powerful, so I
think you ought to have said "much exaggeration."

Give that the JLS says:

<quote>
If the type argument list to the class is empty — the diamond form "<>"
— the type arguments of the class are inferred.
</quote>

then the usage of "type inference" can be defended.

But it is certainly not what type inference is in languages
like Scala etc..

Arne
 
L

Lew

Jim said:
This isn't wrong, but it fixes a problem I never knew I had. Any
competent IDE will expand that for you anyway.

It was added to Java to satisfy the whiners who were afraid they might strain a finger typing "Ctrl-V" or hitting ENTER on the IDE suggestion. Heaven help any of those folks should they ever have to actually work for a living..

Not that I eschew the diamond operator myself now that it's here, but I wasn't clamoring for it beforehand.
 
A

Arivald

W dniu 2012-04-04 03:54, Roedy Green pisze:
I was looking over the table of contents of a book about new features
in Java 7 and came across a reference to the "diamond operator".

It turns out to be simple, but one of the precious bits of Java
syntactic sugar to make it terser.

http://fahdshariff.blogspot.ca/2011/07/java-7-diamond-operator.html

http://mindprod.com/book/9781849685627.html

It will be better to provide "auto" type detector, like in C++.
For example, instead of:
Map<Integer, List<String>> map = new HashMap<Integer, List<String>>();
use:
auto map = new HashMap<Integer, List<String>>();

....and "map" variable will be resolved at compile time to
HashMap<Integer, List<String>>.

This allow very handy construct, like:

auto data = SomeService.getProviders();

In this case type of "data" will be deducted from return type of
SomeService.getProviders().

This will save lot of typing. And save refactoring time in case if
getProviders return type changes. And will auto-adapt to changes in
libraries.
 
L

Lew

Arivald said:
It will be better to provide "auto" type detector, like in C++.
For example, instead of:
Map<Integer, List<String>> map = new HashMap<Integer, List<String>>();
use:
auto map = new HashMap<Integer, List<String>>();

...and "map" variable will be resolved at compile time to
HashMap<Integer, List<String>>.

This allow very handy construct, like:

auto data = SomeService.getProviders();

If 'auto' is a type, it should begin with an upper-case letter. If it's not, you should explain what you intend.
In this case type of "data" will be deducted [sic] from return type of
SomeService.getProviders().

This will save lot of typing. And save refactoring time in case if

It will save virtually no typing compared to current Java idioms.
getProviders return type changes. And will auto-adapt to changes in
libraries.

This idea is incompatible with the current direction of type inference, which is in the other direction, and with Java's strong typing philosophy, andapparently the Powers That Be disagreed that your idea is better, as they didn't implement it.

Your suggestion:
auto map = new HashMap<Integer, List<String>>();

Current idiom:

Map<Integer, List<String>> map = new HashMap<>();

Not much difference in typing, certainly not enough to get your knickers ina twist over.

Your suggestion:
auto data = SomeService.getProviders();
which you describe as "very handy", but violates strong typing, which requires that the compiler know the type of 'data'. If the (presumably static) method you describe were to change its return type, it would break the client code that relies on knowledge of the type of 'data'.

The current inference direction is that the generics of a method declaration are resolved by the invocation context, when possible:

Map<Integer, List<String>> data = getProviders();

where the declaration of the method is something like:

public Map<T, U> getProviders();

Type inference tells 'getProviders()' what types 'T' and 'U' are.

Your suggestion would break those.

So it won't happen for those big reasons.

You should understand that changes to the Java language must meet at least two criteria, irrespective of whether they even provide value (which I don't see that yours does):

- they must not break Java (which yours does), at least not too much,
- they must provide enough value to justify making any change at all (which yours doesn't).
 
D

David Lamb

It was added to Java to satisfy the whiners who were afraid they might strain a finger
typing "Ctrl-V" or hitting ENTER on the IDE suggestion. Heaven help any of those
folks should they ever have to actually work for a living.

Overly harsh IMHO. If you ever change one of those places, you need to
change them all, and having the language feature makes it easier and
less error prone.
 
A

Arivald

W dniu 2012-04-05 20:34, Lew pisze:
If 'auto' is a type, it should begin with an upper-case letter. If it's not, you should explain what you intend.

"auto" is (in C++) reserved word, part of language. It is resolved to
concrete type at compile time, to type of first assigned value.

In this case type of "data" will be deducted [sic] from return type of
SomeService.getProviders().

This will save lot of typing. And save refactoring time in case if
It will save virtually no typing compared to current Java idioms.
This idea is incompatible with the current direction of type inference, which is in the other direction, and with Java's strong typing philosophy,

"auto" in C++ is strongly typed, at compile time.

and apparently the Powers That Be disagreed that your idea is better, as they didn't implement it.

Your suggestion:

Current idiom:

Map<Integer, List<String>> map = new HashMap<>();

Current now... but apparently it is something new in Java 7. Till Java 7
there was lot of redundant typing.

Yet "diamond operator" does not allow to deduct type of variable from
assigned function return value;

Not much difference in typing, certainly not enough to get your knickers in a twist over.

Your suggestion:
which you describe as "very handy", but violates strong typing,

Again no, there is no typing violation. "auto" does not mean "any type",
it mean "compiler, be nice and use type of first assigned variable". It
is just syntactic sugar.

which requires that the compiler know the type of 'data'.

No. Compiler know type returned by SomeService.getProviders(). And will
use this type instead.

Assuming that SomeService.getProviders() declare to return List<String>,
this code:

auto data = SomeService.getProviders();

and this code:

List<String> data = SomeService.getProviders();

have same meaning. Both describe variable named "data" with type
"List<String>".

Note that compiler take type that function declare to return, not type
of really returned object!

If the (presumably static) method you describe were to change its return type, it would break the client code that relies on knowledge of the type of 'data'.

If this method change its return type, code must be recompiled anyway,
both with and without "auto". Currently Your code will stop compiling if
new return type is incompatible with declared variable type.
With "auto", compiler will adapt, and try compile subsequent source code
with new type.
The current inference direction is that the generics of a method declaration are resolved by the invocation context, when possible:

Map<Integer, List<String>> data = getProviders();

where the declaration of the method is something like:

public Map<T, U> getProviders();

Type inference tells 'getProviders()' what types 'T' and 'U' are.

Interesting idea, I do not know that.

But what You can do with this inferred types 'T' and 'U' in
getProviders()? With Java generics not much. On the contrary to C++
templates, You can not use T and U beyond Object type capabilities.
Only Java reflection can save this construct, and make it a bit more useful.
Your suggestion would break those.

Not really. In this case compiler could issue error, due to not enough
information. In this case programmer will be not allowed to use "auto".
So it won't happen for those big reasons.

You should understand that changes to the Java language must meet at least two criteria, irrespective of whether they even provide value (which I don't see that yours does):

- they must not break Java (which yours does), at least not too much,

I think there is no break. Type is exactly known at compile time, and
will generate same bytecode.
- they must provide enough value to justify making any change at all (which yours doesn't).

I respect Your opinion, but disagree. I found "auto" keyword very useful
in C++. This is one of features I really miss in Java.

By the way, I also miss few other things, like "typedef" keyword (for
type aliasing) or templates. Both are great helpers for meta-programming.
Java have "generics", which appears like C++ templates. But only
appears, at first glance. Generics are no real templates, they just
syntactic sugar that hide casting and allow a bit better compile time
type checking. Nothing compared to real templates from C++. Very
disappointing.
Not mentioning security problems with Java generics...
 
J

Jim Janney

David Lamb said:
Overly harsh IMHO. If you ever change one of those places, you need to
change them all, and having the language feature makes it easier and
less error prone.

There may be use cases where this is unequivocally a Good Thing; I've
just never happened to run into one. Not sure I buy the error prone
part, though: if it isn't correct it won't compile.

I notice there's an Eclipse enhancement request to add a refactoring
method to handle changing generic parameters:

https://bugs.eclipse.org/bugs/show_bug.cgi?id=372568

Seems a bit late at this point.
 
J

Joshua Cranmer

If 'auto' is a type, it should begin with an upper-case letter. If
it's not, you should explain what you intend.

The `auto' comes from C++11, where the type of the variable is defined
to be the type of the static value being assigned to it [1]. It is a lot
more powerful in C++, where the language can define some obscene, opaque
hidden types whose exact signatures are left unspecified by the
specification. The largest set of these are the STL iterators, where
iterators look like `std::map<A, B>::iterator', but, when expanded, tend
to be a class with five or six template parameters and a name with way
too many underscores to be sane. The following all refer to the same type:
std::map<A, B>::iterator
std::_Rb_tree<A, std::pair<A, B>, std::_Select1st<std::pair<A, B> >,
std::less<A>, std::allocator<std::pair<const A, B> > >::iterator
std::_Rb_tree_iterator<std::pair<A, B> >

Given that A and B can be very long types themselves, it quickly becomes
obscene just to write a simple for each loop, although C++11 also
introduces a version of for-each loops that ameliorate this.

The other reason for auto is lambda expressions: the type of a lambda
expression is "a unique, unnamed class that has the following
properties", much as the actual type of an anonymous inner class in Java
is a unique, unnamed class which is only guaranteed to inherit from some
method.
This idea is incompatible with the current direction of type
inference, which is in the other direction, and with Java's strong
typing philosophy, and apparently the Powers That Be disagreed that
your idea is better, as they didn't implement it.

The C++11 auto keyword is still fully strongly typed. It's meaning is
best described is "the compiler already knows the precise type of this
variable, and I know what I can do with this type, but I don't want to
spend 15 minutes fighting the compiler to figure out what the right type
actually is." In C++, because of the magic of templates and typedefs,
you can actually spend several minutes just trying to figure out how to
tell the compiler the proper name of a type.

In short, auto is not a matter of dynamic versus static typing, it's a
matter of implicit versus explicit typing. C++ has a fairly complex type
system that has lots of edge cases which happen surprisingly often,
while Java's type system is cleaner, even if you throw in generics.
Given also that I suspect templates are much more abused than Java's
generics, I don't think the auto is as useful in Java as it is in C++.

[1] If you really want to play language lawyer, it's the same type for
the initializer expression as would be derived for template argument
inference.
 
A

Arne Vajhøj

If 'auto' is a type, it should begin with an upper-case letter. If it's not, you should explain what you intend.

Given that it is a C++ keyword, then ....
In this case type of "data" will be deducted [sic] from return type of
SomeService.getProviders().

This will save lot of typing. And save refactoring time in case if

It will save virtually no typing compared to current Java idioms.

It will certainly save some typing.

But saving typing is not really important.
Your suggestion:

Current idiom:

Map<Integer, List<String>> map = new HashMap<>();

Not much difference in typing, certainly not enough to get your knickers in a twist over.

Your suggestion:
which you describe as "very handy", but violates strong typing, which requires that the compiler know the type of 'data'. If the (presumably static) method you describe were to change its return type, it would break the client code that relies on knowledge of the type of 'data'.

It is completely strong typed.

The compiler just infer the type instead of the programmer typing it.

It is available in lots of languages: C++, C#, Scala etc..
The current inference direction is that the generics of a method declaration are resolved by the invocation context, when possible:

Map<Integer, List<String>> data = getProviders();

where the declaration of the method is something like:

public Map<T, U> getProviders();

Type inference tells 'getProviders()' what types 'T' and 'U' are.

Your suggestion would break those.

No.

That could still work.

But you can obviously not infer on both L and R side.
You should understand that changes to the Java language must meet at least two criteria, irrespective of whether they even provide value (which I don't see that yours does):

- they must not break Java (which yours does), at least not too much,

It will not break Java.

C# got it in 3.0 and it did not break anything.
- they must provide enough value to justify making any change at all (which yours doesn't).

That is more an opinion than a fact.

Arne
 
A

Arne Vajhøj

It will be better to provide "auto" type detector, like in C++.
For example, instead of:
Map<Integer, List<String>> map = new HashMap<Integer, List<String>>();
use:
auto map = new HashMap<Integer, List<String>>();

...and "map" variable will be resolved at compile time to
HashMap<Integer, List<String>>.

This allow very handy construct, like:

auto data = SomeService.getProviders();

In this case type of "data" will be deducted from return type of
SomeService.getProviders().

This will save lot of typing. And save refactoring time in case if
getProviders return type changes. And will auto-adapt to changes in
libraries.

Scala does that. And so does most other new functional languages.

But I am somewhat concerned about readability.

In the example the reader may not remember what getProviders()
return and therefor not know what type data is without looking
it up.

Arne
 
S

Silvio Bierman

This isn't wrong, but it fixes a problem I never knew I had. Any
competent IDE will expand that for you anyway.

IDE support is irrelevant in this discussion. Language syntax is not
about typing.

Code needs to be read and reasoned about. The better the syntax, the
less reading effort needed to be able to reason. Java's redundant syntax
in this respect is inefficient and the diamond operator takes away part
of that.
 
S

Silvio Bierman

This idea is incompatible with the current direction of type inference, which is in the other direction, and with Java's strong typing philosophy, and apparently the Powers That Be disagreed that your idea is better, as they didn't implement it.

Wrong if you are speaking about type inference in general. Languages
like Scala and Haskell do it exactly this way and for good reasons.

If you talk about type inference for Java, maybe.
Current idiom:

Map<Integer, List<String>> map = new HashMap<>();

Not much difference in typing, certainly not enough to get your knickers in a twist over.

Typing is irrelevant. Laving out the left hand type increases
readability by removing redundancy. In a different world your example
could have been

auto map = new Map<Integer,List<String>>();

Any keyword as a replacement for auto would work.
Your suggestion:
which you describe as "very handy", but violates strong typing, which requires that the compiler know the type of 'data'. If the (presumably static) method you describe were to change its return type, it would break the client code that relies on knowledge of the type of 'data'.

Wrong in two ways. What you describe is static typing, which is a
specific form of strong typing.

And Arivalds example conforms to static typing. The compiler can deduce
the type of the right hand side expression and uses that is the static
type for the variable. Again Scala and Haskell do it the same way.

The current inference direction is that the generics of a method declaration are resolved by the invocation context, when possible:

Map<Integer, List<String>> data = getProviders();

where the declaration of the method is something like:

public Map<T, U> getProviders();

Type inference tells 'getProviders()' what types 'T' and 'U' are.

Type inference can work in two ways. It can either use an expected type
to resolve the type of a (sub)expression but it can also use the type of
a (sub)expression to deduce the type of a variable or function.

What you describe is the first way using the expected type to determine
what T and U should be. You can have it both ways without breaking
stuff. In Scala you could have:

val x1 : Set[Int] = new HashSet
val x2 = new HashSet[Int]

given a generic type HashSet taking a type parameter. The first one
brings the x1's expected type into the new expression, the second one
uses the type of the new expression to deduce the type of x2.


Your suggestion would break those.

Nope, it would not have to break any existing code.
So it won't happen for those big reasons.

You should understand that changes to the Java language must meet at least two criteria, irrespective of whether they even provide value (which I don't see that yours does):

- they must not break Java (which yours does), at least not too much,
- they must provide enough value to justify making any change at all (which yours doesn't).


I do not think it would be a worthwhile change to the Java language.
Then again, the only reason why I value Java language changes is that
they will sooner promote adoption of the JVM than create opposition.

The JVM is our strategic choice. Java is our workhorse for maintaining
legacy code. For everything new we have moved on to other languages,
mainly Scala. Turning Java into something akin Scala is impossible and
unnecessary.
 
T

Thufir

Typing is irrelevant. Laving out the left hand type increases
readability by removing redundancy. In a different world your example
could have been

auto map = new Map<Integer,List<String>>();

Any keyword as a replacement for auto would work.

While I'm familiar with neither Scala nor Haskell, that seems a bad
idea. What happened to the idea of using a, for example, Ferrari
interface on a Car instance? Sure, the object is a Car, but that Ferrari
interface is used, well, not for convenience per se, but as a reminder
that this Car is not *just* a Car.

You're suggestion is completely contrary to that principle. While I
appreciate that it's easier, I don't get the point.

That being said, in Ruby you instantiate with:

foo = Bar.new

which is quite nice and simple.



-Thufir
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

new JDK 1.7.0_04 and 1.6.0_32 21
trigger static init 16
O.T. German speakers please 3
ctrl-c ctril-v 14
video cards for Java 1
code generation for the ternary operator 33
probing SSL websites 1
bugs.sun.com 11

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,280
Latest member
BGBBrock56

Latest Threads

Top