top | item 16515860

Representing the Impractical and Impossible with JDK 10 “var”

105 points| pents90 | 8 years ago |benjiweber.co.uk

128 comments

order

pents90|8 years ago

While I submitted this, I would like to voice my opinion that I am against "var" in Java. People may ask, "Why should I have to enter in the type if the compiler can infer it for me?" My answer is twofold: 1) You or some other maintainer will need to know what that type is later when reading the code. Of course, "var" is meaningless, requiring you to dig back one or more steps to determine the actual type. 2) You don't actually need to enter in the type, any competent IDE can do it for you.

So I'm not sure what we are saving here. When has the time spent typing in code ever been a bottleneck in software development anyways?

This is my feeling from having worked extensively in Java as well as languages that support "var": C# and Swift. I feel like my productivity goes down when I have to support code that uses inferred types. There also seems to be a performance hit when compiling code with inferred typing, although that may be circumventable with better compiler tech, who knows.

trixie_|8 years ago

I'm pro var

* I write code a lot more fluidly with var. When I go back to writing non-var code (enforced by some departments) I find that it breaks my focus on solving the problem at hand. I end up writing my code with var and then going back and replacing my vars with the type names.

* I find code a lot easier to read. I can understand the flow of the logic easier, the variable names are enough. Unless you have the type definition memorized, just knowing the type isn't going to help you much. You're going to need an IDE either way.

* Refactoring is easier. For example, changing the return type of a function from array to list means a lot less code needs to be changed as a result if the callers were using var. The compiler will tell you if there's any instances where a caller was using an incompatible property.

* Reviewing is easier. Your change set is a lot smaller when changing a type name.

Seriously you won't miss it when it's gone. People also used to prefer Hungarian notation.

skybrian|8 years ago

This is an old argument. A counterargument is that if the IDE can auto-insert the type for you, it could also show you the type on demand.

But this assumes that when reading code, you're always using a tool that can show you the type. Auto-inserting is only needed when writing.

One thing to be wary of is that even when the compiler shows you the type, (in an error message, for example), if it's complex, it will be difficult to understand. If you want to write simple code, perhaps it's better to avoid or encapsulate complicated types?

bcoates|8 years ago

Maintenance programmers already have to deal with concealed mystery types, every time you do

   f(g())
it's just syntax sugar for

   var temp = g()
   f(temp)
Now at least programmers aren't tempted to do gratuitous function nesting rather than introducing a variable just to avoid cluttering code with an unimportant type name.

arcticbull|8 years ago

I felt the same exact way about Rust. A few years later, it's totally liberating. I do get lost from time to time, but the savings relative to spelling that stuff out is enormous. IDE support where you mouse over and it tells you what the inferred type is even better, IMO, as you get the "right" answer with full precision not the "coerced" wherein you may have erased some type info.

mpfundstein|8 years ago

People said the same thing about auto in C++. Few years later and everyone I know (and codes C++) loves it and uses it all the time. Its a great addition and like lambas will certainly improve how we write Java

zamalek|8 years ago

> You or some other maintainer will need to know what that type is later when reading the code.

The Microsoft rule is to only use var when the type is obvious from the assignment. That essentially boils down to new, cast and anonymous types.

ot|8 years ago

> "var" is meaningless, requiring you to dig back one or more steps to determine the actual type.

> You don't actually need to enter in the type, any competent IDE can do it for you.

These two points contradict each other. Any competent IDE can visualize the inferred type even if you don't spell it, for example as a tooltip.

This is not (only) about typing, it's about the visual noise and redundancy caused by explicit types. Plus, as the article illustrates, the ability to give names to expressions that have very complex types, reducing the need for type erasure.

Marazan|8 years ago

Reading long nested generic type declarations in Java is an absolute utter mental pain. Being able to vat that shit will be a god send.

moomin|8 years ago

C# developer here: my own take is that there are times when vat makes code harder to read, but your team should value identifying and avoiding that. In any event, it’s still perfectly possible to elude type information using techniques such as never declaring a variable in the first place. From this perspective it’s just one more tool in the armoury for writing readable code.

In its favour: It’s surprising how much code doesn’t really need the types written out to be readable (a discovery that will shock Python developers not at all). Furthermore, refactoring said code has less busywork in it.

As a side note: There’s one weird benefit of var not mentioned in this. Namely, you’re guaranteed there’s not going to be a cast. This is a serious problem in C++ where assigning the result of a function to a variable can have arbitrary side effects. (It’s not that bad in Java since pretty much all you can do is cast to interface.)

gravypod|8 years ago

I'm glad that I'm not the only one in the Java community who is extremely against `var`-like constructs. Large type inference is an anti-pattern.

People usually fight this with "why would I need to type it if the compiler can figure it out!?" but those people don't understand the cardinal rule of software engineering: code is not for the compiler or the computer to understand, it is for the programmers to understand. If this wasn't the case then more people would be using APL or similarly esoteric languages.

Adding the extra effort of recursing down the rabbit hole to find the first type being used does not sound like it will make Java more friendly.

scarface74|8 years ago

Why as a maintainer should var make the type harder to know? It's right there on the screen when you are initializing the variable and hopefully you're naming your variable something to make it obvious (not Hungarian notation).

If you your method is too large to fit on the screen, the method is probably too long.

But what competent IDE doesn't allow you to just hover over the variable to the know the type?

djhworld|8 years ago

I quite like type inference in typed languages (e.g. Go, Kotlin etc), and when I read about it coming to Java I wasn't that fussed, just saw it as a nice to have.

It didn't occur to me before I read this post that the complex, chained generic types that you can sometimes get with "builder" like patterns (e.g. SQL generators) can become incredibly complex, so this would tidy that up quite nicely

akerro|8 years ago

Well, I don't like streams in Java, they make code much slower, it looks fancies, but in real time, streams are often abused and make code run longer in almost every case I measured (I took some methods from Github, SO and reddit comments). Equivalent for loop/for-iterator loop is much faster. Solution: you don't have to use it, you can educate others how to use it properly.

jayd16|8 years ago

Var makes refactoring way easier while being just as safe and informative.

ionised|8 years ago

Can't say I'm happy about this. Type inference really doesn't belong in Java in my opinion.

Not only is it ambiguous to developers who might be maintaining the code later, I find it much worse for readability. People tend to start writing OO code like it is Javascript which is is never good.

rmrfrmrf|8 years ago

> any competent IDE can do it for you.

My biggest gripe with Java by far is the implied IDE requirement.

vbezhenar|8 years ago

I don't like the fact that `var` breaks class hierarchy. I can write `List l = getList()` and then variable `l` will have only methods from `List`. If I'll decide to change `getList()` return type, it'll be easier to migrate the code. With `var` variable `l` probably will have something like `ArrayList` type and I can accidentally use methods from `ArrayList`, even if I don't really need them, tying this code to concrete class.

It's obvious that everyone will use `var` everywhere, so using `var` in one place and explicit type declaration in another probably would be even worse.

cm2187|8 years ago

On your point about the IDE helping you, there are two use case.

object i = new object();

I agree you only type once, the IDE will suggest object after new. But in that case the type is needlessly redundant, var could be use without making the code any less readable.

object i = myfunction();

Here the object is sementically useful but given that you have to type it before you type the name of the function I don't see how the IDE can possibly help you. Not only that but unless you know the return type of that function by heart it forces you to go check it out before you even start the line. And if you are using generics (or valuetuples) that could be a long type name.

matt2000|8 years ago

I agree. It seems very clear that code readability is reduced by var-like type hiding. When I'm doing code review and I see "var address = contract.getAddress();" what is the type of that variable? I have no idea.

koolba|8 years ago

Any sufficiently sharp tool can cut deeply in the hands of the untrained. The answer isn't to dullen our blades, it's to find better apprentices and journeyman to work with.

makecheck|8 years ago

I’m OK with implicit typing when the real type is “nearby”. For instance, if 2 lines away I see “Array of ObnoxiouslyLongTypeName”, I gain nothing by having to restate ObnoxiouslyLongTypeName for an iteration loop on that array. Similarly, a method or variable name may strongly hint at what it is.

Also, verbosity in programming is definitely a hindrance to maintenance. It’s generally easier to understand what’s there when you can remove some noise.

seanmcdirmid|8 years ago

There is no appreciable performance hit for locally inferred types given that the compiler isn’t doing much. Globally inferred types can take a hit, though most of those are based on Hindley Milner which can be pretty efficient.

yinyang_in|8 years ago

What are your opinions about python, as it has no explicit type for readability.

spion|8 years ago

Its so funny, watching Java fans talking about silly things like `var` whilst their language gets more obsolete every day. I'm so sorry, but basic type inference won. Can you please go away so we can get a good ecosystem and a good language (with first class support VM wise) to go with it in a single package?

On a side note, its getting very tiring to rewrite the whole ecosystem every time a language is being annoying. Can the CS types please work on this real world problem a little instead of going knee deep into homotopy type theory? Please solve this somehow: allow engineers to leave a language without leaving its library ecosystem - lets make libraries super-portable, easily.

vbezhenar|8 years ago

I'm very disappointed that they didn't make `val` keyword. Very simple change but code becomes significantly more readable and a lot of bugs will be compile errors.

threeseed|8 years ago

Java is not Scala though.

By default everything has always been mutable e.g. collections, variables. And so whilst I support val I can appreciate the difficulty in switching everyone to an immutable by default mindset. Especially given the lack of decent functional transforms e.g. map, flatMap, filter in Java.

kochthesecond|8 years ago

I am also disappointed by this, I want it to be more painful to use rebindable references than final (immutable) references.

saagarjha|8 years ago

How so?

saagarjha|8 years ago

The “impossible” part of the title is an interesting one, since it mirrors how the arrival of lambdas coincided with the arrival of auto in C++ because such types are similarly impossible to represent. As I’ve mentioned in another comment in this thread, I think Java and C++ are very similar with regards for the need of type inference because they end up having a lot of the same issues.

ScottBurson|8 years ago

This will be nice, but what I really want in Java is a type alias feature (what C++ calls "typedef"). This would be particularly helpful for function parameter and return types, which 'var' won't help with.

dionian|8 years ago

This is one of those things I really liked immediately when switching to scala. I wonder if java 10 is going to further drive adoption of scala. The difference in collections API is already argument enough to switch IMHO (hence I did)

rad_gruchalski|8 years ago

Scala has those as well. They’re besutiful.

Insanity|8 years ago

It's one of the things I really missed when going from C# to Java, but with IntelliJ, the typing experience is very similar from C#.

Imagine I want to have a variable like:

     Person p = new Person("John");
All I would type in IntelliJ is:

     new Person("John").var
After pressing "tab", that will autocomplete for me and put the focus on the variable name so I can rename it from the default inferred value.

vbezhenar|8 years ago

Also you can use "introduce variable" refactoring (ctrl+alt+V in Windows). Type "new Person("John")" and immediately press ctrl+alt+v.

adrianmonk|8 years ago

Don't most decent IDEs support something like that? In Eclipse you can just type

    new Person("John")
And then hit Ctrl-2 L.

walshemj|8 years ago

Can some explain the fist example says infers the type is right there in black and white

var foo = new ArrayList<String>();

It literally says exactly what foo is !!

kinghajj|8 years ago

Yes, but in current Java one would have to write

ArrayList<String> foo = new ArrayList<String>()

Or, at least

List<String> foo = new ArrayList<String>()

Whereas with `var`, as you show, the compiler infers the type. Proponents of this point out exactly what you did: the type is right there, so why should the programmer have to write it twice?

exabrial|8 years ago

My opinion is it you have the time to declare a variable, then you have the time to hit control-space to put the type. Not putting the type communicates less information to the next guy. If you "don't care" about the type, then why are you declaring a variable in the first place? Just chain the call.

lkjlakjsdlfkj|8 years ago

"let" is more elegant IMO.

ajkjk|8 years ago

I always found 'let' to be such a strange name. What on earth is appealing about it?

The usual variable declaration syntax is <type> <name>; it's not a stretch to imagine the type as 'var', a catchall type. But 'let'? Let is a verb; it should be in a place where functions, not types, go. It makes sense in "let x in {}" type expressions, and it kinda makes sense in Lisp, but I don't see any argument for it in a C-like language.

coldsauce|8 years ago

do you mean the word itself? or some implementation detail is more elegant?

saagarjha|8 years ago

let as a drop-in replacement for var, or something semantically different?