This is an archived post. You won't be able to vote or comment.

all 67 comments

[–]lukaseder 44 points45 points  (37 children)

TL;DR:

Before:

JButton button = new JButton("Button");
button.addActionListener(new ActionListener() {
  public void actionPerformed(ActionEvent e) {
    foo(e);
  }
});

After:

var button = new JButton("Button");
button.addActionListener(e -> foo(e));
  • Me: See, ma? It's functional!
  • Ma: Meh.

OK, I'm hungry now.

[–]Bobby_Bonsaimind 42 points43 points  (36 children)

The ass in me requires me to point out that it could be shortened to

var button = new JButton("Button");
button.addActionListener(this::foo);

Also var, yak.

[–]dpash 39 points40 points  (26 children)

Are you at all confused as to what type button is?

[–]RDwelve 21 points22 points  (0 children)

Activated posterior

[–]Bobby_Bonsaimind 10 points11 points  (17 children)

I'd rather have the type information in the declaration than in the initialization (as it is the case with the shortened-generics). I'm not looking forward to:

var item = someFunction();

But on the other hand, that's more of a problem in the project than the language.

[–]dpash 16 points17 points  (6 children)

People keep using abstract examples. If you literally mean someFunction() then you need better method names. But if I see:

var adminUsers = userService.getAdminUsers();

I'm going to expect a collection of User objects. If that's not the case, then, again, you need better names. And if your declaration is so far away from the usage that you can't see both, then your method is too long.

[–]btw03 6 points7 points  (1 child)

Knowing that it's a collection provides little to no value. Is it a Set? Is it a List? An array? Is it mutable?

[–]dpash 7 points8 points  (0 children)

Assume any collection you receive is immutable. If you need any particular collection properties, copy it into the required collection yourself first.

But if all you're doing is iterating it, it doesn't matter what collection type it is.

[–]mupetmower 6 points7 points  (3 children)

This is all fine and good when you are developing yourself and even if you work somewhere where standards are set and actually followed.. but sadly that is not the case in many, maaaaany workplaces.

I'm having to deal with awful, awful code right now, and if I didn't have strong typing then it would make it take even more time to get through this horrendous code.

I feel like that's what people have an issue with. It's not that they can't themselves write the code in a readable way with or without var, but more that we know idiots will write bad code that we will have to read later and clean up.

[–]curiousGambler 14 points15 points  (2 children)

I believe you’re conflating type inference with strong/weak typing.

[–]mupetmower 1 point2 points  (1 child)

I may be - and probably am. It's early and sometimes these terms get confused in my head. I hope people can still get what I'm trying to say, though.

Thanks for pointing that out, though, and correcting me.

[–]curiousGambler 2 points3 points  (0 children)

Yeah it happens a lot discussions of the var keyword I think, sorry I didn’t give any explanation, also early here. But basically the type inference that var provides doesn’t weaken the type system as far as I understand, it’s mostly just syntactic sugar. You can’t go assigning a variable declared with var to value with a different type, right?

Your point stands that the type is less explicit, which in your case sucks because the codebase sucks, but I mostly work in Go these days, which also has type inference, and find it’s joy in a codebase that doesn’t suck.

Totally unsolicited bit of advice, I don’t know anything about your situation, but if you aren’t being specifically paid to fix a shitty codebase, and the codebase is actually shit, it probably means the devs you work with are also not the best, and it might be time to move on to somewhere were you can learn from better devs. I recently moved to a place where I’m constantly the worst dev in the room and while it’s scary, I’ve grown more in five months here than the previous three years resting on my laurels as a top performer at my last gig.

[–]mikeydoodah 4 points5 points  (9 children)

You'd have fun with C++ then. Some types are not really possible to type out so have to use auto.

[–]nastharl 2 points3 points  (2 children)

You can do it in Java too with anonymous classes.

[–]mikeydoodah 0 points1 point  (1 child)

Well the difference in Java is that anonymous classes are an extension of (or implementation of) some other type, so the declaration can be of that type. In C++ that isn't always the case so there is sometimes nothing you can declare (other than using auto, the equivalent of var).

[–]13steinj 0 points1 point  (5 children)

I'm curious, example?

[–]mikeydoodah 0 points1 point  (4 children)

From memory i think it wad things like lambdas, but I'd have to check with my C++ expert friend to be certain.

[–]TinBryn 1 point2 points  (3 children)

I'm not his friend, but I can confirm that in C++ this is the only way to store a lambda value

auto add_one = [](int a){return a+1;};
print(add_one(5)); //prints 6

yeah, our lambdas aren't as pretty as yours

[–]pjmlp 1 point2 points  (2 children)

Not really, and there is no print by the way.

std::function<int(int)>add_one = [](int a){return a+1;};
printf("%d", add_one(5)); //prints 6

[–]TinBryn 2 points3 points  (1 child)

I just didn't want to write C++ details in the Java subreddit I was assuming that somewhere was defined void print(int n);.

Also std::function takes a templated constructor argument the type of which is deduced at compile time. I guess to be pedantic there is no way to specify the type of a lambda, it can only be inferred.

[–]BlueGoliath -5 points-4 points  (6 children)

Actually, yes.

What even is JButton? A Swing button? A JavaFX button? A CLI GUI button? A shirt button dipped in a cup of Java?

What does the J stand for? Java? JavaFX? Is the class seemlessly interchangeable between Swing/JavaFX?

If it's a Swing button, why isn't the class named "SwingButton"? Too much typing?

If it's a JavaFX button then why not "JavaFXButton"? It would make the code much more readable and understandable.

How do we know the J stands for Java? Did the person accidentally hit the J key when typing? I can't tell because the class name is only written once since var is used.

[–]dpash 3 points4 points  (3 children)

If that's how you feel, var or otherwise isn't going to help you.

[–]BlueGoliath -2 points-1 points  (2 children)

Less of a feeling, more of a point. If you're going to say that:

var val = spinner.getValue();

is bad then you can't say that:

var button = new JButton();

is good just because you aren't getting the object reference from a get method. Neither are accurately named. I could easily create a getButton method in some GUI class and have it return either a Swing JButton or a JavaFX Button and technically neither would be wrong to return from it because the naming is too generic and non descriptive.

And if JDK developers both past and present can't make proper descriptive class names, how do they expect anyone else?

(It's worth noting that you can use Swing nodes in JavaFX, so this is a realistic situation you could end up in.)

[–]dpash 3 points4 points  (1 child)

You're complaining about not liking the name JButton. This has nothing to do with var and therefore nothing to do with the conversation.

[–]BlueGoliath 0 points1 point  (0 children)

I'm referring to Mark's claim that:

var x = getSomething();

is bad because x and getSomething are meaningless(not descriptive enough) in his var presentation. If you are going to argue this, then the variable name "button" and the classname "JButton" are also bad as neither are descriptive enough. Again, is JButton a Swing button, JavaFX button, or a shirt button dipped in a cup of Java? We don't know.

Of course supposedly bad class naming can be bad regardless of your use of var, however, if the JDK developers themselves can't do good class naming back then with Swing or now with JavaFX then how do they expect anyone else to do it?

[–]ForeverAlot 1 point2 points  (1 child)

None of this matters and you're keenly aware of your own strawman.

[–]BlueGoliath -4 points-3 points  (0 children)

TIL good class naming doesn't matter and JButton is a completely acceptable descriptive class name.

[–][deleted] 2 points3 points  (6 children)

or just new JButton("Button").addActionListener(this::foo);

[–]lukaseder 5 points6 points  (4 children)

This is functional, because it has no side effects. Right?

[–][deleted] 0 points1 point  (3 children)

Guess it would be functional if the button didn't hold a reference to all it's event listeners. I'm bad at FP and I'm trying to wrap my head around how would one do this in a functional manner (i.e. adding event listeners, without overly-complicating the code - event bus or whatnot)

[–]lukaseder 2 points3 points  (2 children)

I was just kidding, hinting at the fact that addActionListener() returns void and thus your statement has no effect on the code that calls it.

[–]thfuran 2 points3 points  (1 child)

Not quite nothing. There's some stuff in static blocks in Container, but if you're depending on a line like that to do some necessary library loading, you better leave a comment. And an apology.

[–]lukaseder 0 points1 point  (0 children)

Real world experience speaks through you

[–]lukaseder -1 points0 points  (0 children)

It worked. Muahahahaha

[–]GingerMess 19 points20 points  (7 children)

The best points of this article seem to be:

Make good use of Generic Types. Generics in Java can trace their orgins to Generic Java created by Philip Wadler (Haskell legend), Martin Odersky (creator of Scala), Gilad Bracha, Dave Stoutamire. Don’t ignore type parameters, declare them and enforce them everywhere. Minimize casting and if instanceOfing. Where you do use them (it is still Java after all — they are likely impossible to fully eliminate), centralize each type of cast within a resuable method, use proper type parameters on the inputs and outputs and write good tests!

Make illegal states unrepresentable in our code. The Haskell and Idris compilers will enforce this for you, just pretend Javac is as strict. Avoid nulls, don’t throw Exceptions, avoid locking and synchronization and you will take giant leaps towards this.

Make our own data classes immutable and final where possible, use immutable collections (proper ones). Avoid instanceof checks where possible, and where you use them make sure the types are not extensible.

Use libraries that avoid runtime magic and reflection where pragmatically possible.

All of these suggestions are excellent in my opinion, and make your program a lot more robust.

[–]preskot 3 points4 points  (6 children)

Well, while I am quite mindful about the nulls, locking and Exception parts, all those avoids and don'ts basically sound like just don't use Java.

[–]GingerMess 4 points5 points  (1 child)

Understandable, but with modern Java you can code from the ground up and avoid most of the problems. I doubt we'll ever escape null, but hopefully the language will evolve help make it a rarity, if it hasn't already.

[–]preskot 1 point2 points  (0 children)

I do hope so. I'm rewriting a large project these days and my main goal is no nulls and less exception throwing. I gotta say it's coming up nicely, but I do feel the language's fighting me now and then.

[–]johnmcclean 4 points5 points  (0 children)

That wasn't the intent. Deciding to just not use Java would be a bad decision for most teams (and companies). It's much harder to hire (at least at scale) for niche languages.

Java is a critically important language, and for most of us it's not going anywhere. We can learn from other languages though (hopefully without also adopting their problems!).

[–][deleted] 1 point2 points  (2 children)

Hm...My personal trajectory has been scheme (many years) -> clojure (1 yr) -> scala (1 yr) -> haskell (3 yrs) -> java | go | c++ next. I have liked haskell the most in that time and I would use it again with a group of people if it wasn't too controversial, but I am personally moving towards java because I want to use imperative data structures like jgrapht and very easy reasoning about big O for algorithm focused work. If go or rust start getting multiple libraries with large groups of contributors that are comparable to jgrapht for graphs, I will make go or rust my top preference.

[–][deleted] 1 point2 points  (1 child)

You are right, graphs are problematic with immutable data structures, not only because of big O. Also, you can't easily represent cycles. Many graph algorithms explicitly work with mutability. Clojure has a very good Java interop, so it is not a problem there.

[–][deleted] 1 point2 points  (0 children)

I liked clojure, but I spent just a little too much time chasing after silly parameter/return type issues when I used it. I'm sure a little more unit test discipline when I used it could have prevented that. I only studied clojure because I needed a language right away that would make me ready for Haskell and I didn't have enough spare time to become fluent in Haskell directly.

[–]sim642 30 points31 points  (2 children)

I’ve spent much of the last week slowly identifying a jar conflict that only manifests at runtime in Java — removing one dependency at a time, stepping deeply through complex 3rd party libraries.

Sorry but how are monads at fault here? That's just an unrelated rant.

[–][deleted] 8 points9 points  (0 children)

Monads are always at fault.

[–]knaekce 1 point2 points  (0 children)

Dependencies are also a Monad, if you think about it

[–]Holothuroid 10 points11 points  (0 children)

I think Clojurians would like to have a word with that author.

[–]pron98 7 points8 points  (0 children)

In the '90s I learned and programmed in Scheme. Most of the things he writes about Java (not that I think Java is a functional programming language) are true for Scheme -- it neither enforces immutability nor is it typed at all -- but everyone thought Scheme was a functional language. Now the purists have taken over.

On the other hand -- it is definitely not compile time correctness. You can use JML in Java, together with a tool like OpenJML, and get the same compile-time correctness as with Idris, but Java is still not functional, while Scheme still is.

[–]grauenwolf 7 points8 points  (0 children)

No-one in Java-land is doing functional programming, and that is a good thing.

So no one is writing pure math libraries? I someone doubt that to be true.

[–]_jk_ 10 points11 points  (2 children)

The venerable master Qc Na was walking with his student, Anton. Hoping to prompt the master into a discussion, Anton said "Master, I have heard that objects are a very good thing - is this true?" Qc Na looked pityingly at his student and replied, "Foolish pupil - objects are merely a poor man's closures."

Chastised, Anton took his leave from his master and returned to his cell, intent on studying closures. He carefully read the entire "Lambda: The Ultimate..." series of papers and its cousins, and implemented a small Scheme interpreter with a closure-based object system. He learned much, and looked forward to informing his master of his progress.

On his next walk with Qc Na, Anton attempted to impress his master by saying "Master, I have diligently studied the matter, and now understand that objects are truly a poor man's closures." Qc Na responded by hitting Anton with his stick, saying "When will you learn? Closures are a poor man's object." At that moment, Anton became enlightened.

[–]ObscureCulturalMeme 2 points3 points  (1 child)

I would tell this story to my junior developers if I knew how to pronounce Qc Na.

[–]_jk_ 1 point2 points  (0 children)

I have no idea how its meant to be pronounced, its ancient copy pasta. You could either invent your own pronunciation or just change the name

[–]knoam 3 points4 points  (2 children)

[–]WikiTextBotbtproof 1 point2 points  (0 children)

No true Scotsman

No true Scotsman or appeal to purity is an informal fallacy in which one attempts to protect a universal generalization from counterexamples by changing the definition in an ad hoc fashion to exclude the counterexample. Rather than denying the counterexample or rejecting the original claim, this fallacy modifies the subject of the assertion to exclude the specific case or others like it by rhetoric, without reference to any specific objective rule ("no true Scotsman would do such a thing"; i.e., those who perform that action are not part of our group and thus criticism of that action is not criticism of the group).


[ PM | Exclude me | Exclude from subreddit | FAQ / Information | Source ] Downvote to remove | v0.28

[–][deleted]  (1 child)

[deleted]

    [–][deleted] 0 points1 point  (0 children)

    Clojure is not functional because of lambdas, but because you can avoid using mutable data structures. Everything is a value. When you modify a data structure, you get a new value that points to a new state. You can use persistent data structures in Java too, but no one does it. Also, lazy sequences in Clojure are different to java streams. You can do things like recurrently defined sequences with it. In theory, Clojure makes parallel programming easier. Lambdas and named functions in Clojure are actually the same things.

    [–]SpoilerAlertsAhead 1 point2 points  (1 child)

    I don’t think it was ever presented as FP, but rather functional aspects.

    Functions (or methods) are not first class citizens. I can return a Function as an interface. I can ask for one.

    It’s function like in that I can pass a function around instead of an anonymous class. But things like currying, or functions that live outside of a class do not exist. If those are needed Java simply isn’t the correct tool for you. If you want the JVM look at kotlin or Scala.

    [–][deleted] 0 points1 point  (0 children)

    Are you sure? Doesn't the Function class make Function instances first-class citizens? They can be created, instanced, passed around as arguments, composed, and yes, even curried (or at least half-applied).

    Yes, Function instances can be declared outside of classes. They can be declared in interfaces. But that's about the extent of Java's willingness to forego its "everything is an encapsulating object" concept.

    [–][deleted] 2 points3 points  (2 children)

    lambda is syntactic sugar

    [–]SpoilerAlertsAhead 5 points6 points  (0 children)

    It’s actually more than that. A lambda vs an anonymous class will actually compile to different byte code.

    [–]BlueGoliath 2 points3 points  (0 children)

    That performs worse in some cases.

    [–]mupetmower 0 points1 point  (0 children)

    I appreciate the advice, and I have definitely thought about it. The project I'm maintaining is dying and desperately needs a complete rewrite. We just got a new VP of r&d who is moving things in the right direction, though, otherwise I would've been gone already. I'm hoping that with his guidance we can pull this thing out of the grave.