Skip to content

Instantly share code, notes, and snippets.

@harsh183
Last active December 25, 2020 05:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save harsh183/c9ddfed189c55527be7cab22d5a57820 to your computer and use it in GitHub Desktop.
Save harsh183/c9ddfed189c55527be7cab22d5a57820 to your computer and use it in GitHub Desktop.
Blurb I wrote on CS 125 Forum about explaining Type Inference

I've gotten many questions about this from both students, and current existing course staff since type inference is a reasonably new age concept that is getting picked up in the programming languages of the 2010s and 2020s.

The lesson gives a pretty good starting point, especially the 7-minute walkthrough here on the basics of type inference.


Talk is cheap, show me the code

I redid a few of the older problems using var type inference across a few of the past homework problems to see this in action. I highly suggest checking these out.

  1. Variables and Types
  2. Variable Operations
  3. Array
  4. Multidimensional Arrays
  5. Football CSV

It's pretty easy for me to record more, so if anything is too hard to understand, I can redo it, or create more videos. I've solved pretty much every single problem of this semester with massive abuse use of var


Theory

Type inference is Java smartly figuring out what is the type of your variable is from the context around. Compilers of the 60s and 70s were more straightforward and didn't allow this kind of thing making you explicitly set the type of every variable. Type inference was a good thing because it led to an overall more maintainable code, and compilers could do all sorts of safety sanity checking.

To set it up, we use var, and Java does its magic.

var num = 5;
var decimal = 5.5;
var alive = true;
var name = "CS 125";

It's not guesswork

When people first see that it's easy to think of languages like Python, JavaScript or Ruby which have duck typing, the language is trying it's hardest to guess what the type of the variable is while the program is running. Wrong guesses to runtime errors (bad) causing the user trouble.

Type Inference, on the other hand, is exact, it uses rather complicated mathematics and compiler logic to precisely determine the type of every variable where you use var, during compilation. That means if you mess up, it gives a compile-time error (good) which you can fix right away over Python style with a prayer that things go well.

On a good enough IDE (ex. IntelliJ, VSCode) if you mouse hover, it can show you the inferred type as well, so if you're worried you lose out information or readability, it does not happen.

Only for local variables

var add(int a, int b) {
  return a + b; 
}
// the return is an int, but Java refuses to infer

A lot of people then ask "If Java is so smart? Why can't it infer function parameters, return types or even class variables?"

Java usually can but doesn't allow it on purpose to improve things for a programmer. By forcing you to add type information to function returns, parameters and classes you give Java the idea of what the different areas of code take as input and output basically, and type inference can then take over almost everything in the middle.

Type information does improve readability and future maintenance when it is in those crucial headers. When skimming the code, you will often read those but not the implementation details itself. Type inference is for the implementation details, where most of the time, type information is redundant noise and makes the code less clunky.

Quality of Life Improvement

Mainly, type inference improves the experience for the programmer. The user of your program will not notice any difference at all, but often this means shorter, cleaner code, fewer errors and quicker programming time (especially on exams).

Instead of spending time interrupting your flow of thought wondering what the type of every little variable is, use var in place and then change it up if the Java compiler complains. Use it to increase readability and decrease the cognitive load on yourself.

You don't have to use it in every case, so you get to decide, sometimes having the type info for a few variables will make it more readable, especially when variable naming is far vaguer.

var emailId = "hdeep2@illinois.edu";
var parts = emailId.split("@");
String netid = parts[0];
var domain = parts[1];
System.out.println(netid + " at " + domain);

For example, netid here may not be the clearest. Is it an int since it's an id, is it a String or some other type so adding String adds to the clarity of the code and creating more focus. But for the rest of the steps, I'm not too worried about what the reader thinks the type is so then I use var for the rest.


(me replying)

[quote="jackiec3, post:2, topic:27639"] I’m of the camp that would rather have variables typed out and avoid using type inference when I can [/quote]

Haha everyone starts this way. I suggest just trying it for a few days and see if it sticks.

One of the biggest complaints people of all experience have of Java is that it's extremely verbose and pedantic, and it mostly becomes from types. This is a good thing because it's a safety net but type inference gives us a best of both worlds scenario.

Often I think it adds unnecessary cruft to the code. Made up example.

JSON<List<People>> jsonPeopleList = api.get("...");
List<People> peopleList = jsonPeopleList.parse();
Person firstPerson = peopleList.get(0);

And this code is already a mouthful, and quite honestly I don't really think having those helps readability because it's just more pieces of information most of which I don't think is relevant to a skimming reader. (and don't get me started on C++ types std::iterator<...>)

var jsonPeopleList = api.get("...");
var peopleList = jsonPeopleList.parse();
Person firstPerson = peopleList.get(0); 
// the last type I actually care about

I think this is better because the it's more relevant detail that actually matters. I want the reading programmer to know the final result is a Person but the steps before don't matter, if I messed those up Java compile will yell at me and if I really want to know I can mouse hover to figure out what types I want. Otherwise, it's just redundant and takes focus from what matters.

Person a = new Person("hdeep2");
var a = new Person("geoff");

Or in this example, it's very obvious what the type the object is, repeating it twice just adds noise.

Overall I think type inference is just another abstraction, I care about type I can say which, and when I don't (most of the time) I just use var as if it's second instinct. In my classes like cs 126, 225 it made a large difference overall since I was finishing up things much faster with lesser code due to this (and other clever tricks of the trade).

This is also available in most modern compiled languages by now, C, C++, Kotlin, C#, Swift, Rust, Golang, TypeScript, Zig etc. so feel free to give the feature a spin in any of those, the details are basically the same in each.


(another reply by me)

The reason people feel afraid of type Inference is the way a lot of people think it is very similar to Python or Ruby which type errors. Repeating again, type inference is part of a strong, static system. It never guesses wrong unless your program is wrong (which the compiler figures out as well).

When you need to see what the type is, your IDE can tell you itself. You can’t really do that in Python. It’s definitely not cheap and dangerous, in fact it often makes your code more adaptable to change and refactoring than otherwise. Let’s say you want to change a function from float to double, with type Inference you’ll have to change it in 2-3 places and the rest of the program just updates.

@harsh183
Copy link
Author

The full forum thread: https://cs125-forum.cs.illinois.edu/t/type-inference-some-more-detail/27639/11

This will have UIUC Account access restrictions though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment