Java is becoming more like Rust, and I am here for it
joshaustin.tech
joshaustin.tech
In Rust you can take any data structure and mutate it. There are hardly any invariants that you can force, unlike in Java. For example, strings are mutable in Rust. This, coupled with not being a language managed by GC, makes persistent data structures not practical or desirable.
Of course, mutability in Rust is very controlled, as variables being mutated can't be observed in an unsafe way. So it matters less if strings are mutable. E.g., you won't be able to mutate a string while it's used as a key in a hashmap.
But the fact is that, while Rust provides a high degree of safety, functions in Rust are usually side effecting, which means no referential transparency, no equational reasoning, hard to refactor, etc.
In Java, culturally speaking, you don't see much immutability, but when you have immutability, it tends to matter much like in FP languages. And Rust is definitely not one of those languages.
What if a memory location not marked "mut" is allocated by the compiler in the executable TEXT segment, so the virtual memory page is itself mapped read only?
Are you certain you can get away with what you said, within the promises of the compiler?
Are we talking about different things? I'm writing Rust too (and decades of C) and feel I'm missing what you're describing, perhaps.
This isn't strictly true. Almost all Java code I see day to day are immutable classes outside of those being used with JPA.
In Rust on the other hand, even though ref cells are a thing as well, the main approach to mutation is through mutable bindings and mutable references, which preserve const-correctness (inspired by C++), i.e. there is a certain degree of transitivity in the guarantees around immutability. When I see an immutable reference in Rust and pass it to a function (or a method), then, outside of few special cases, I can reasonably expect it to stay unmodified. In ML I can’t, unless the code is written in a very unoptimal way, i.e. with persistent data structures anywhere and everywhere, and still the type system won’t give me any hints about that.
I see what you're saying, and definitely agree in a way, but also those two things aren't incompatible.
Rust didn't invent those concepts, but Java is becoming more like it by incorporating them. If Rust is much more widely known about than other languages that have those things, it may be more informative to people to hear "Java is getting some stuff from Rust" than to hear a statement that apportions the credit in more detail.
We have languages like Haskell and, before it, ML. And I know ML didn’t invent it. We also have Scala, and for Scala, we don’t even have to leave the JVM. There’s also F#, which is a kind of cousin-of-a-cousin to Java.
Rust has sum types and immutability because tons of people thought these features were important, and lots of languages adopted them in parallel with the appearance of Rust.
> I would not be surprised if Kotlin and/or Scala were more influential in bringing this to life.
But yeah, I agree, generally weak article. I don't think it shows that "Java is becoming more like Rust" at all, because of the two listed features.
F# "originated as an OCaml implementation", which runs on .NET with some C# interop support?
I like about HN that everyone is so friendly about this type of thing. I personally don’t have a lot of patience for people who think new things are the greatest inventions and ‘the old is catching up’ (in this case Java catching up with Rust) while everything came from elsewhere originally. If you want to openly say these things, please research them first and attribute properly. But indeed it is good here we try to educate not shame or insult like some other communities.
Anyway: I would say people should learn bottom-up as we don’t need to invent the wheel every few years that way.
I believe FP did give us the pattern matching syntax for destructuring variants though.
Once projects Valhalla and Panama land Java will be transformed again. Exciting times.
In a way, the lack of threading allowed `async` to be implemented without gotchas. In languages with first-class thread support, `async` implementations can run into thread issues. (Will the continuation run on the same thread? Does the code care?)
JavaScript is inherently async because the concept of the event loop is baked into the very language runtime itself.
In Java you can achieve a single threaded async runtime by instantiating a SingleThreadExecutor and having all your application code running as jobs posted to this executor. But because you can opt out of this model or use something like a ThreadPoolExecutor it's harder to bake in an `async` keyword into the language that is as simple as you have in JavaScript.
> JavaScript is inherently async because the concept of the event loop is baked into the very language runtime itself.
Ok, I hadn't thought about it this way. Early UI frameworks for java had this property as well. I don't know about the implementation. But there was some kind of message loop running, and you'd register event handlers, and events would get dispatched to your handlers.
You could argue that was the framework, not the language. Maybe I'm wrong, but I think of the message loop as being a property of the execution environment (DOM/node) rather than the language. Maybe that's not a real distinction though.
Disclaimer: I'm just the messenger here so you might hate what follows, the community is choosing the words.
Concurrency as a keyword is increasingly being used to differentiate single-threaded event handling from parallel processing (threads). As long as event handling is quick enough, it can give the illusion of parallel processing. And in some cases it can outperform parallel processing because the cost of context switching between events can be lower than context switching between threads. See https://medium.com/@caophuc799/nginx-architecture-and-why-ca...
The async keyword, in practice, simplifies the callback boilerplate required to handle the event model. When used in communication, async is increasingly being used as a word to describe "Single-threaded Concurrent Functions Built On Hidden Event Handling", because there is no succinct way of saying STCFBOHEH in English.
So: JS has async/STCFBOHEH/context-switching on its functions by default whereas Java's functions are (by default) executed in order without async/STCFBOHEH/context-switching.
My understanding of "async" as a language feature is basically support for an `await` keyword. Having a message loop and event dispatcher seems like a less useful definition, but good to know, I guess.
> It is super-common to observe "I saw feature F in language X, then I saw it come to Java, they must have gotten their inspiration from X." And while sometimes this is true, it is far more common that both are drawing inspiration from a common source or literature, sometimes even one that predates either language. (It is also super-easy to confuse "Language X was the first place I saw feature F" with "X invented F.")
Another in reference to getting inspiration from OCaml [1]:
> This is exactly the reaction that I was describing by "might elicit strong reactions from some", which is what I would call a "who moved my cheese" objection. Good, now we've got it out of the way. I had the same concern for the first few seconds after seeing this idea (the inspiration came from work being done in OCaml), but it didn't take much longer to see how it fit into the bigger role of switch.
Another from Ron Pressler [2]:
> Obviously, we do borrow features from less popular languages (primarily ML, which was never popular), but only when we think they're the best way to address a real need of Java's millions of mainstream developers and not just because those languages' self-selecting users love them.
This has all been discussed multiple times on the /r/java subreddit.
[0] https://www.reddit.com/r/java/comments/11322uy/jep_draft_imp...
[1] https://www.reddit.com/r/java/comments/18hglp5/effect_cases_...
[2] https://www.reddit.com/r/java/comments/18ynhn1/which_kotlin_...
It has all the goodies I like in Rust (multiplatform, decorators, FP, pattern matching) but with a GC/JVM to back it.
I personally like Rust since I can drop down to low-level embedded projects and stick with one language, but depending on what interest you, Kotlin can be an excellent fit.
[1] https://openjdk.org/jeps/441 [2] https://openjdk.org/jeps/444 [3] https://openjdk.org/jeps/430
Record types, immutable after construction: https://www.c-sharpcorner.com/article/c-sharp-9-0-introducti...
Warning when a switch isn't exhaustive: https://learn.microsoft.com/en-us/dotnet/csharp/language-ref...
I don't believe C# has anything like the exhaustive switch over a sealed interface that the article is talking about.
OK, then I am going to regard this as "around the same time". Every new C# feature is released "in November", since .NET major releases drop in November every year. That's the release cadence.
But language design decisions of what to add in that release are not done inside that 1 release month, or in any 1 month. They are done over much longer time periods, often incrementally over successive years.
Maybe people are actually using it but not talking about it? Not sure.
These days it's actually more interactive and dynamic to develop applications with than a lot of dynamic languages, thanks to the improvements over the years.