Hacker News new | past | comments | ask | show | jobs | submit login
Java 21 VirtualThreads vs. Clojure Lazy Seqs (clojure.org)
215 points by grzm 12 months ago | hide | past | favorite | 147 comments



The Clojure devs should be aware that the synchronization pinning problem is intended to be temporary and doesn't apply at all with GraalVM native images. One of the Loom developers talks about it here:

https://mail.openjdk.org/pipermail/loom-dev/2023-September/0...

So they could also just choose to ignore this problem for now.


We are aware, and that is one of the options. :)


The other thing I didn't mention is that the change to remove biased locking a while back has also had an impact in some places that do almost always uncontended locking, so we're kind of considering that too.


A lot of Clojure projects choose to stick with the LTS releases though, so it might take a while before this problem disappears on its own, even if fixed in the JVM.


In fact, the officially supported Java releases for Clojure are all LTS releases. This is also reflected in their CI. At the moment, that means 1.8, 11, 17, and 21.

I would also like to mention, for non-Clojure users: it took ages for Clojure to finally get off Java 1.5. The compiler was still emitting 1.5 compatible bytecode as late as 2018. Since the release of Clojure 1.10 (17 December 2018), the minimum Java version was bumped up to 1.8, in the sense that the compiler now emits 1.8-compatible bytecode.

There is a strong emphasis on moving slowly and NOT breaking things in the Clojure community. Likewise, if you look at the most recent Clojure survey results, the vast majority of people were still on 1.8 and 11 releases.[1]

[1] See Q24 in https://www.surveymonkey.com/stories/SM-_2BH3b49f_2FXEkUlrb_...


I actually do feel like this is partly what's responsible for Clojure's relative success in industry. If you have a company with a ton of Java 5 code, and you want some of the sexy functional programming features, your options basically boil down to "upgrade everything to the newer Java 8 to get maps and optionals and whatnot" or "just write this new service in Clojure that will happily interop with our Java 5 code".

I'm not making a judgement on which decision is better, but I can totally see the appeal, at least in the short term, for people choosing Clojure, especially if they think that Clojure's API will be largely unchanged in the Java 8 update. It doesn't hurt that Clojure is just broadly a really pleasant to work with, at least in my opinion.


> If you have a company with a ton of Java 5 code...

You are in deep deep trouble already, just process-wise. If you're making money hand over fist you might be able to afford to do that, but choice of language is not even on the radar in terms of what needs fixing.

Now, if you mean in terms of digging out of that hole... just upgrade to newer dependencies, newer JDK versions, etc. That's the way to better performance, better memory usage, better GC, better everything... and THEN think about the language you're using.


> You are in deep deep trouble already, just process-wise.

Code is usually a much smaller piece of company's business process than we developers like to think.

> If you're making money hand over fist you might be able to afford to do that

Here's the problem though: the vast majority of companies on the planet don't "make money hand over fist", they just have small to reasonable profit margins. And most businesses can't just risk losing what's already been working for a decade just because some developers want a new shiny thing every six months.

That's the reality which JVM and Clojure folks take very seriously, but is very often overlooked by younger people.


> Code is usually a much smaller piece of company's business process than we developers like to think.

I agree.

Btw, I think you inverted the meaning of my sentence regarding 'hand over fist'. I was saying that staying on an old version is asking for trouble and is going to cost a lot more than upgrading.

> That's the reality which JVM and Clojure folks take very seriously, but is very often overlooked by younger people.

Ah, the irony of being called young because of a comment I made :). I'm an old hand at this point.

FWIW, my shop also stayed on JDK 8 for a bit longer than we should have, but that was largely because of upstream dependencies. We're currently on JDK11, but again just because there are some upstream dependencies that are holding us back from JDK17. (It's mostly to do with the infamous module system change. It's a good change overall, but some projects have been super-slow to adapt.)


These are very good points. The programming language used is a tiny sliver of the pie chart required to run a profitable company. The entire “technology” portion of that pie chart is still only around 20% (at best) of a profitable company.


You can definitely run a lot of 1.5 code on 1.8 and never notice


To be entirely fair, there's arguably little overlap between devs that stick to LTS, and devs that will play with JVM virtual threads on Clojure (before the Clojure team has any particular, public stance on them).


Yes, especially since the use case for virtual threads is so niche.


Is this sarcasm, or just generally true in the java community?


I can't think of a project I've worked on in the past 10 or so years that couldn't benefit from virtual threads. Right-sizing your thread pools in an environment with a lot of IO is/was a pain in the ass.

Many of the core concurrency constructs in Clojure has separate functions for when you are doing something that is blocking vs not blocking. If it were all virtual threads this distinction generally wouldn't matter.


Not just that - the kicker is everything that already exists (libraries, JDBC drivers, etc) are now just automagically non-blocking too if you seed the thread pool with a virtual thread factory.

I can't remember the last time such a transparent, drop-in-able change was so impactful for just about everything.

While it doesn't remove the need for the event/reactive/async paradigm in all cases, it does removes the need for async code just for the sake of being non-blocking.

Code can now be written much more clearly, and still be non-blocking. That's huge.


Neither for me (I'm in the Clojure camp), it just seems to me there aren't many situations where you'd need millions of threads. Plus we've got core.async to reach for to multiplex many control flows on one OS thread - though I feel it's more needed when targeting JS (ClojureScript) and the single-threaded world there.


I'm coming at this from a Erlang/Elixir background , Where we basically have "virtual threads" but they aren't at the OS level. It's easy to use and making things concurrent (or parallel) is often trivial. Whether it's 1 extra virtual thread or millions of virtual threads, the code (and the horizontal scaling of that code is the same)


I love core.async (been using it since... 2014 I think... both Clojure and ClojureScript), and yes, core.async/go basically was/is solving (some) of the same problems. But there's a number of gotchas around (go ...) blocks...

Without being an expert on the core.async internals, I believe core.async can potentially benefit tremendously from this, by the virtue of being a powerful and super-elegant API for communicating between different parts of an application (typically within the same JVM process). Now it can continue to do that, while (likely) being free from most macro gotchas...


It's niche if you don't have much traffic/request volume/etc.

Once you have even an arguably relatively small amount (100s to 1000s of requests per second) it can be a game changer in terms of efficiency.


Are there published case studies or other empirical evidence available with numbers about this?

OS threads in Linux are fast and you can have a lot of them. Eg https://news.ycombinator.com/item?id=37621887


Just try starting ~100,000 threads that each sleeps for ~60 seconds in your JVM and check if you can succeed! :)

``` (run! (fn [x] (future (Thread/sleep 60000))) (range 100000)) ```

(hint: likely not...)

TLDR; Efficiency difference: you can think of virtual threads as being about 1,000 times (3 orders of magnitude) less expensive, in the general case. Exception: If you are only doing CPU-only work, regular threads will be better (that's not how most web servers/services operate).

But if you're waiting 100ms of ms for your database (or any network) to respond and you have many of those (blocking) method/function calls in flight... virtual threads are the way to go in terms of efficiency.

Great video explaining all of this (at timestamp, all 30 min is worth watching):

17:05 Making threads less expensive: by how much? https://www.youtube.com/watch?v=5E0LU85EnTI&t=1025s


On a wimpy old desktop running lots of other stuff I got 75000 threads with that snippet (had to increase max_map_count tunable first with sysctl -w vm.max_map_count=500000, a knob well documented for bigger thread counts). Considering that in a real world use case with that much concurrency (such as the "100k threads frequently waiting for 100ms db queries" scenario), I'd be using a bigger machine and there'd also be some actual application context data and TCP connection state dwarfing the thread memory requirements in those blocked contexts, I'll still call virtual threads solving quite rare use cases, pending stronger evidence.

I don't doubt virtual threads are efficient when microbenchmarked against OS threads, but there's only so much to be gained when optimizing a part of the system that wasn't a bottleneck to begin with.

(Also I hope in the scenario we have a beefy DB that can exploit the concurrency available in this many pending concurrent queries per client, and isn't just putting them in ever queue! I guess it could, maybe it has 1000 read replica servers, each with 100 attached SSDs or 100 cores serving from in-memory data)


Right... but using virtual threads I got 1,000,000 (in a second or two...) and likely for fraction of the memory. And I can even get many millions without a problem.

I agree that for a low volume typical CRUD-only server that never bursts above a few dozen requests per second that's not an issue.

Messaging is one special "rare" case.

Imagine a messaging channel in Slack/Discord/Telegram/WhatsApp-type app, where there's thousands of participants (say 10,000) in one channel. 1 person posts a message...

9,999 messages are generated (one to for each of the other participants). One might say, that can be handled with a few machines...

Now imagine a person posts something super interesting to the channel where 100 people respond with an emoji reaction almost instantly.

Now you have 100 * 9999 = 999,900 (!) messages, all within a few seconds! And this is for just one message _reaction_. Each one of those messages likely involves multiple steps of IO (sending/receiving data over the socket, writing to one or multiple databases...). So a thread might be blocked for hundreds of milliseconds at various times, which would ultimately likely require 100-1000x more servers to operate as scale increases.

The thing is that you _can_ write a program efficiently using regular threads by using asynchronous techniques. Another name for such style of programming is _callback hell_ :) . And when something does go wrong, it is a lot harder to debug.


As pron always says.. that's a risk of staying on an LTS release. You're choosing to not receive updates.


It seems to me by design or by indifference Java is now tired of JVM ecosystem languages at large who claim innovation by surface level changes while relying heavily on JVM bedrock.

Now Java is moving fast and they are taking JVM compiler, runtime, class metadata etc along where Java, the language is headed.


Not only Java, that is the fate of all guest languages, as they don't evolve alongside the platform, always require additional tooling and most language cultures than start making their own little islands of idiomatic libraries instead of directly using platform libraries.

Since most platforms are leaky, one ends up needing to master two ecosystem in parallel, eventually it gets tiring and always cost extra in development.

C++, Objective-C and Typescript get around this problem in UNIX and Web, as they are extensions of the platform languages, not something completely different.


Yep agree with all you said. Nowadays new job every year people at work are scaring me with their enthusiasm to replace decades old solid Java applications which are performant and working fine with Kotlin and what not.


I wouldn't advocate for replacing/re-writing old stuff - but you should try out Kotlin for backend work. It's amazing.

Java programmers will have only a small learning curve before feeling productive, and can gradually get more comfortable with idomatic Kotlin as they progress through their journey.

Kotlin, as a language, was very well through out, letting you use as much or as little of it as you are comfortable with.


For me personally Kotlin does not bring that much to the table over a modern version of Java. Sure if you're stuck in Java 8 it can be a win, but compared to Java 21 it just doesn't bring enough to warrant the switch for me.


Honestly the main thing I find killer about Kotlin over Java is its stricter null safety (types do not permit null values unless you mark the type as nullable with a "?" suffix). (I know Java does have the @Nonnull annotation but it's extremely verbose to use much and Java doesn't enforce its use on values that are expected to be non-null, which both greatly diminish its usefulness.) I've been spoiled by languages like Typescript and Rust which have great null safety like Kotlin, and it's very annoying going back to a language without it and questioning whether a null is expected or possible for every single value.


I wish I could get a strong sense of the hype around null safety. Sure, I would like to have the extra expressive option. However, optional has been fine for me. I still barely use it. It has to be at least 3-4 years since I last encountered a null pointer exception in my daily java programming. I feel like there are plenty of other things that pain me on a daily basis that rank far higher on my asks for the language. Collection and stream ergonomics cause constant pain, for example.


Infinitely chainable expressions, .let, .also and friends. You shouldn't overdo it (lengthwise) and it's almost hilariously superficial, but I miss it in every other language since.

Tying down a value to a name only if you have something meaningful to say in the name, and only when the value is actually finished instead of being a work in progress, that gives me great piece of mind and frees up mental resources for other things. I wish every language had a "kotlinized" sibling that simply added the scope functions on syntax level (or a subset of the scope functions, not sure you need a zoo that size)


I personally find let, also, and friends to be a clarity nightmare. For me, they make reading code harder.


It's not always better, I give you that. If something does not work as expected you might even find me transforming code to conventional imperative style. But I feel like I have a much better shot at getting it right in the expression chain style, and in all styles if scopes are not polluted by dubious intermediaries and/or badly named one-callsite functions thanks to letisms. By the time the "let tax" grows too high, chances are that the block in question is big enough to make the "factored into a function tax" bearable.


I’ve seen this sentiment a lot and I don’t understand it. I actually feel like very little has been added between Java 8 and Java 21. Virtual threads is probably the biggest thing, and it looks very promising, but the language itself is still a chore to use, and Kotlin does a good job at cleaning a lot of that up.

I think Kotlin is at risk, though, of having the JVM force them to support two competing models to accomplish the same thing - coroutines and virtual threads is a good example (although Java still doesn’t have language level structured concurrency). This could really make things messy.


> I’ve seen this sentiment a lot and I don’t understand it.

I just don't think any feature of the language of Kotlin is that much better than Java's implementation. I'm also a big supporter of brevity != clarity when it comes to code.

What language feature in Kotlin do you think is that much better?


I was you not that long ago. I've had the same conversation with a lot of other Java developers too - they/we always say the same things.

It's weird being on the other side of the fence now - hearing the same things I used to say.

Kotlin was a gateway drug out of not just Java, but OO/Solid and into FP for me (FP being another thing I used to not "get"). The beauty of Kotlin is you don't have to ever write FP code if you don't want to - but you will want to before too long.

I would recommend trying it out for yourself. It's Spring integration is amazing, and you'll have a great time. Write even a little Kotlin and you'll have an "ah ha!" moment and everything will forever be different.

It's one of those things where you need to experience it for yourself before you actually understand how great it is. There is no argument you will hear that will convince you, sadly. I was the same once...


To me Kotlin is different enough to be annoying to learn, but not different enough to matter that I use it over Java. So it just kinda feels like a waste of time.


You can do many FP things in Java as well, as it is a multi-paradigm language, hell, Kotlin is not even particularly functional-y.


I'll agree that Kotlin is not hardcore FP (although you can get there some of the way with Arrow etc.), but FP in Java is clunky.

- Having to remember the difference between "Function", "Consumer", "Predicate" and "Supplier" is weird. In Kotlin (and basically every other typed FP language that I know), I just write the type signature the natural way.

- Having to use streams in order to use map, etc., is noisy. Why weren't these APIs retrofitted to collections?

- Checked exceptions are a pain with functional code, e.g. map.

- Mutability is still the default behaviour of almost everything in Java, save records (and strings).

etc.


> Having to use streams in order to use map, etc., is noisy. Why weren't these APIs retrofitted to collections?

Sure, methods along the lines of the following could have been added:

  public <R> List<R> map(Function<? super E, ? extends R> mapper) {
      return stream().map(mapper).toList();
  }
Yes, having them would make Java less verbose in the case where you only want to do a single map, filter, whatever operation on a collection, but I'm personally glad that they weren't because they produce extremely inefficient behavior when chained. So, it would add a performance footgun to save ~18 characters.


But are these things enough to warrant me a full switch of programming language and ecosystem? Not for me.

- I don’t think this is really that big of a deal.

- Using streams is actually preferred so you don’t cause a performance nightmare and kotlin you has to use asSequence anyway.

- I thought checked error handling was all the rage nowadays?

- Mutability is absolutely fine if you’re not going over a thread boundary.


In Kotlin, asSequence gives you lazy behaviour (i.e. chains of map, filter, etc. are merged the way it's automatically done in Haskell), but if you don't care about the performance penalty, you can just call map, filter etc. on eager collections too. I'm of the opinion that you shouldn't prematurely optimise, for small enough data, it often doesn't matter much.

And checked exceptions are widely seen as an anti-feature - I don't think any other language has them, with the possible exception of Swift (see below), and for good reason. Other languages encode errors (more or less ergonomically) in the type system (e.g. Rust, Haskell, and to an extent it's what Kotlin advocates as well), and that has the advantage of playing well together with other language mechanisms - e.g. no extra allowances need to be made so that map works with them.

But for the sake of the argument: Swift also has something similar to checked exceptions, but only in the sense that functions can either throw or not throw. However, Swift also at least has constructs like "rethrows", which lets you say that a function such as map should throw iff the higher order function it wraps throws.

Java simply decided that it doesn't need to deal with this problem at all (for whatever reason - they simply could have added something like "rethrows") and now it's up to callers to deal with the incredible awkwardness that is using FP with Java library code that makes heavy use of checked exceptions.


Null safety checks and if being an expression are major pain point resolvers that are still not available in Java (OK, maybe pattern matching helps the if-expression part, because pattern matching IS an expression in Java). Oh, and the legacy library APIs, which Kotlin elegantly wraps with FP-compatible classes. Instead of fiddling with streams (which also lack some basic operations, or have some not so nice API), you can just .map or .fold over your (read-only by default) collection. Not only less verbose, but also easier to use and understand. Having said this, these are fairly minor things, which may not warrant a switch to Kotlin, if you are otherwise happy with Java...


> I think Kotlin is at risk, though, of having the JVM force them to support two competing models to accomplish the same thing - coroutines and virtual threads is a good example

I don't think it's that good an example, though there's some merit to it. Kotlin coroutines, to me, target three main use cases:

1. An abstraction over an underlying threading model. Get threaded execution without having to explicitly deal with thread pools and such. I'd consider structured concurrency to be part of this use case.

2. A way to write non-blocking code that is structured as if it were blocking. (Incidentally: I love Kotlin's decision to make "await" opt-out instead of opt-in.)

3. A way to write code that generates sequences of values without having to either write an explicit class that maintains state across calls or use callbacks/CPS. Or in other words, a way to use the "yield" function.

Use case 1 still makes sense with virtual threads. Run your coroutines on an executor that uses a virtual thread pool instead of a platform thread pool. If you prefer the coroutines API, you can still use it for structured concurrency and such.

Use case 2 is much less interesting in the presence of virtual threads; you can just write blocking code directly, no need for the language to turn it into async code for you.

Use case 3 has nothing to do with threads to begin with, so it remains exactly as valuable as before and there's no reason to change any existing code at all.

Do coroutines get less useful in the presence of virtual threads? Absolutely. But they aren't competing with virtual threads; there are substantial non-overlapping use cases that make them a worthwhile language feature.


> I actually feel like very little has been added between Java 8 and Java 21.

var, records, sealed types, and pattern matching make a huge difference in how Java is written. A lot has changed since 8.


This is a pretty unimpressive list for 9 years of progress, and is merely a small subset of features Kotlin was already providing.

I left the Java world for the C# world around 2008 and then returned to the Java world last year. C#/.NET changed much more significantly much faster. Almost all of the significant differences in day to day life with respect to the Java language and standard libraries that occurred between 2008 and 2022 are due to changes introduced with Java 8.


The issue with these new structures is they're necessarily clunky, to maintain interoperability with non-modern Java. Java's backwards compatibility is legendary, but is also why some of it's newer features are often criticized as not being as good as they could be.


It's one thing to say, "very little has been added between Java 8 and Java 21," and something else entirely to say, "newer features are often criticized as not being as good as they could be [to maintain backwards compatibility]."


I don’t think any of then is clunky - hell, pattern matching is straight better in java.


Kotlin is the closest thing to a "better Java" that I've found. I've used it with Spring Boot and the interoperability with Java is fantastic. A Java dev would have no problem picking it up quickly (as opposed to Clojure and even Scala).

I say this as a Clojure fan, there are many instances where I'd probably choose Kotlin nowadays. You can also mix JVM languages within the same application; I've found it rather useful to sprinkle some Clojure into a Java/Spring application for certain tasks. Maven and Gradle both have tooling to handle it :)


If you're into FP stuff, using Arrow within Kotlin takes you to that next level. It even works with Spring/Boot.


Couldn't agree more! It's particularly disappointing when you need to work on an older java codebase after finishing a Kotlin project. You'll constantly miss features


> You'll constantly miss features

Like what?


Nullable types, module level functions, context receivers, nicer type signatures for functions, a better standard library (e.g map works directly on lists without the stream.map crap)


Personally, these features are not something I feel like I would constantly be missing. I don't constantly feel like I'm missing them after switching from JavaScript, at least for not having to call .stream(), context receivers (which Java provides with ScopedValue), or signatures for functions.

I'll give you nullable types, though I personally don't struggle with null at all.


Even C# seems like something stuck in the 1990s compared to Kotlin. (I know it’s not a high bar).


Not kept up with the times in regards to C# 12 features?


C#'s problem is it's quickly becoming C++ in that it doesn't just have the kitchen sink, it has three kitchen sinks...

Unlike C++ though, one day the powers that be will just remove features as part of yet-another framework rewrite and you'll just have to deal with it.

The other issue is just how tightly coupled C# as a language is to the .NET framework/platform. Some of the things people like C# for are actually framework things and they don't realize it because that separation isn't as clear as with Java and say, JavaEE or Spring or $X.

If you talk to a C# developer - of course they're using .NET and of course they're using Entity Framework - to them, there's no other way. It's inconceivable that any other library or framework might do it better than Microsoft's official offering... and then you'll find the official offering to be lacking in fundamental ways.

Talk with a Java developer and you'll find there's a lot more diversity of frameworks and libraries being used - so there's a lot more differing opinions on priorities and a lot more good ideas being tried out or implemented everywhere. The communities are vastly different in that regard.


Collection literals are going to be fantastic. Many don't know that there is actually momentum to keep moving right into Dictionary literals.

There is a "roles" proposal and investigation team. This roles proposal is going to unlock so much potential it is bonkers.


Collection literals are a pointless extension of the pattern matching syntax added to get around the fact that there is no way to name a generic type in C# without specifying its type arguments.

It's yet another double down on object initializers instead of writing constructors and factories, and unlike using a factory you have to fully express the result type of the collection instead of having it inferred (they are "target typed", another feature that probably should not have been added).


There is a pattern matching aspect but I think the energy behind it is largely motivated by a desire to clean up syntax when working with data structure based APIs and DSLs.

I've read the proposal, design meeting notes, and GH conversations. Not seeing a compelling counter argument here.


What do you think I’m missing that makes C# 12 not a-lot-of-lipstick-on-a-java-pig?


It is still another syntax, with idioms moving away from JVM, their own little islands of Kontlin only libraries, and only works on InteliJ/Android Studio.

I don't see any value in Kotlin outside Android shops.


While true it has it's own syntax, the syntax is better than Java and more ergonomic. With that said, you can write Java in Kotlin - and by that I mean Kotlin code that looks almost exactly like Java. Heck, you can have .java and .kt source within the same project all mixed together if you want.

Kotlin libraries are interoperable with Java and vice versa. In some specific cases, a Kotlin library needs a little syntactic sugar to make it work with Java like a Java developer would expect, but it's easy to do. Going the other direction though - Java library used in Kotlin, zero issues, it just works. Some Java developers don't even realize they're already using Kotlin - take a look at OKHttp and friends...

Lastly, there's Kotlin support is all major IDE's, including IntelliJ of course, but also Eclipse and likely whatever editor/ide you prefer. Kotlin is basically just a bunch of libs.

I would argue Kotlin is better outside of Android than in Android. For backend work, particularly when coupled with Spring/Boot, it's freaking amazing. The Spring team has put in an impressive amount of work to make Kotlin a first-class language within the ecosystem, and it really shows.


Try to call Kotlin co-routines from Java.

Telling me there is Kotlin support in Eclipse only tells me you never actually tried it, specially after JetBrains ramped down the team that was doing the now stale plugin.


You should look harder before saying it doesn't work. Updated 10/6/2023[1]

Coroutines are a specific paradigm within Kotlin, and should not be in library code anyway. With the addition of JVM Virtual Threads, the need for Coroutines is significantly diminished anyway.

It's anecdata, yes, but I've written a lot of Kotlin code and do not use coroutines. Kotlin really just lets you do what you want - as much or as little idomatic code as you need.

Kotlin on the backend is amazing. You really should give it a try. Java sucks badly, in comparison (I say that as a former Java nerd...)

[1] https://marketplace.eclipse.org/content/kotlin-plugin-eclips...


And you should read before posting random links,

   After installation of the Kotlin plugin the Java plugin is not running anymore. I cannot open a Java project anymore.

   The log file says:

   !MESSAGE org/eclipse/jdt/internal/ui/refactoring/actions/RenameJavaElementAction$AjcClosure1
   !STACK 0
   java.lang.NoClassDefFoundError: org/eclipse/jdt/internal/ui/refactoring/actions/RenameJavaElementAction$AjcClosure1
    at org.eclipse.jdt.ui.actions.RenameAction.<init>(RenameAction.java:60)
    at org.eclipse.jdt.ui.actions.RefactorActionGroup.<init>(RefactorActionGroup.java:372)
    at org.eclipse.jdt.ui.actions.RefactorActionGroup.<init>(RefactorActionGroup.java:206)
    at org.eclipse.jdt.internal.ui.packageview.PackageExplorerActionGroup.<init>(PackageExplorerActionGroup.java:139)
    at ...


You copy/pasted an error some random person on the internet had in June due to using an incompatible Eclipse & plugin versions?

The beauty of Eclipse is the ecosystem. If that official Jetbrains plugin doesn't do it for you for some reason, then use another one[1].

[1] https://marketplace.eclipse.org/content/enhanced-kotlin-ecli...


I've worked in several JVM backend projects, and Kotlin has been a stark improvement over Java (at least up through version 17, the most recent with which I've worked directly). Compose, and Compose UI, are tremendously promising technologies; I've shipped desktop apps with Kotlin for multiple platforms, and compared to just about every other desktop UI framework, it's a clear winner in terms of productivity and an ability to GSD.

All that to say, I believe that Kotlin has a lot of value, independently of Android.


> I don't see any value in Kotlin outside Android shops.

Developer experience is important to some people - not just devs, but those who seek to recruit and retain good ones.

Of course, if you're looking to hire massive numbers of butts-in-seats (gov work, large enterprise shops, etc) I suppose Java is probably the ideal choice.


"Only works on IntelliJ" is patently false. Stop spreading FUD.


Where is Kotlin support for Eclipse and Netbeans?

Prove me wrong.


Do you use Eclipse? Have you looked at the available plugins?

There's nothing special about Kotlin. It's a bunch of libraries for runtime and compile time... like anything else you use.


It is my main Java IDE.

There is a difference between supporting a language with a Notepad++ like experience, and what JetBrains was doing before ramping down the Eclipse plugin team, as means to sell more InteliJ licenses instead.


What do you believe you are missing?

It compiles fine with Maven or Gradle, it provides auto-prompt/complete/hints. It just works.


Same experience as in InteliJ, which JetBrains no longer provides.

And above all, no crashes left and right.


I'll ask again more clearly - what is the "same experience" you are missing?

Kotlin is plugins for Maven/Gradle, and classpath libraries. There is no magic going on here...


I did a year of Kotlin in a recent job. I liked it, but not enough to prefer it over Java - especially with the recent updates to Java. YMMV


That would only be a bad thing if the Java ecosystem was good to begin with.

From my perspective it is terrible enough that the language specific wrapper library has 10x to 100x the usability of the Java option if you use it directly from Java. For example, GORM for Groovy is significantly better than Hibernate even though it is built on top of Hibernate. It is so good that I chose to use groovy once, not because it made sense but simply because Hibernate is so terrible, the cost of a different language was outweighed by it.

I don't give a damn about most JVM features. They don't change the crap ecosystem at all. I personally despise the JVM for being incredibly memory inefficient as well. None of this is going to change.


That's an interesting hypothesis. Is that applicable to platforms other than programming languages?


And many developers are tired of Java making minuscule improvements to developer ergonomics while pretending to be progressing, when even now, it doesn't have features that other languages have had for 30 years.


Based on pure statists about the number of important, business critical java-applications that run most of the internet, it seems like it just straight doesn’t matter in any significant way.


Maybe it doesn't matter to you, but it does matter to me.

All the power to people who enjoy working in Java, but that doesn't have to make me like it.


The JVM and Java the language have always been intertwined. The same people that develop the language, develop the VM. Lots of optimizations in the VM know specifically about Java the language idioms and implementation details. Check out this function which helps determine if instance fields are trusted: https://github.com/openjdk/jdk/blob/edd454b502b9bacde5549282...


Still waiting for VS Code to support Java 21. Java is not the language to use without an IDE.


I can't imagine doing Java in VS Code instead of Intellij. Is there something I'm missing out on?


No idea. I use IntelliJ for Java/Kotlin and emacs for everything else (Clojure, Python, JS, etc). I still encounter the occasional lunatic who uses eclipse or netbeans.

I know VSCode is the "standard" editor for front-end devs, and so I assume some of them are trying to keep their code editor when moving into backend work. I have to believe it's not as good - for a time I really, really tried to make emacs work for Java development, but it just.... doesn't :)


The reason I use VSCode is Code Server[0]. It is certainly not as powerful as IntelliJ, but the I have to get used to it because the web-based IDE is a must for me.

By the way, unless my English is terribly bad, calling someone lunatic for their choice of IDE may not be a great idea.

[0] https://github.com/coder/code-server


It's a hyperbole that no reasonable person would get offended by.

So nobody except Emacs users. ;)


Lunatics all.


Lunatic meaning maniac or fool.


I was being facetious, of course :)


Same for IntelliJ: JetBrains Space

But it also supports Gitpod, Google Cloud, GitHub Codespaces, Amazon CodeCatalyst, and Connect to Coder [0]

There's also Dev Container, that gives all the developers the same dev environment as a container.

https://www.jetbrains.com/help/idea/remote-development-a.htm...


Doesn't it require you to have JetBrains locally installed on your machine to be able to connect?


Dunno, I always have it installed.

BTW, CodeWithMe [0] urls can automatically install some viewer to be able to participate in the call, don't know if it's the full editor or not. But they can install the full editor the same way for the above.

https://code-with-me.global.jetbrains.com



At my job a lot of people hate on Eclipse, but honestly I find it quite nice. I use IntelliJ for my private projects and think both are on par.


Base vs Base installations, Intellij is better. Ergonomically, I find Intellij better.

However, my experience with it has been that once you get every plugin you need loaded it becomes dog slow and even basic stuff like reference jumping becomes a slow, tedious slog compared to Eclipse.


Yeah, I used both Eclipse and Intellij and Eclipse is actually good IDE. Both have advantages and disadvantages, but I can not say that Intellij is better.

The most hate for Eclipse, in my job, comes from people who never used it. They basically dislike how it looks like and that it is not exactly same as Intellij.


fellow eclipse die hard here ...

It's definitely a very complex beast but once you do master that complexity it is such a power tool. Even though I routinely do work in IntelliJ I miss various things enough from Eclipse that I always go back.

I just wish it had proper Kotlin support.


How's the Kotlin language server performance for you? When I last tried it was using up so much resources for the simplest Kotlin file. I gave up and moved to intelliJ (which incidentally offers plenty of refactoring features you don't get in vscode)


Kotlin is horrible in every IDE other than IntelliJ/AndroidStudio and JetBrains has little motivation to fix that.


That was my feeling too. Kotlin in Vscode was not usable. My computer ground to an halt as soon as I typed something


Intellij does a lot, and VS Code is very light. Some people prefer an IDE that does a lot, but some don't care and benefit from VSC being lightweight. Also, some projects are janky, and VS Code is easier to get to ignore that jank. Plus, I find VS Code's hotkeys to be much more intuitive as a long-time Windows user and hotkey addict.

No matter what I do locally, the final word is a pipeline build. A command line is closer to that than either IDE, so at times I've really appreciated VS Code mostly getting out of my way.


> VS Code is very light

Did you actually measure that? In my experience, once you've added the bare minimum of language support/LSP that's far from the case (and at comparable memory footprint VSC ends up doing less and is just less capable)


Honestly I didn't care about any objective measure, development "felt" less laggy in VSC.


Exactly. Being lightweight is important when you are running the thing on some cheap VPS. Also the multi-lunguality, since you don't have "room" for multiple IDEs.


> VSC - lightweight

Are we talking about the same thing?


If you've seen IntelliJ, you won't have any problem calling VSCode lightweight :D


Though I prefer IntelliJ, VS Code is fine.

I sometimes switch to VS Code just to use Lischke's terrific ANTLR plugin.

https://marketplace.visualstudio.com/items?itemName=mike-lis...


Brian Goetz just gave a talk about all the stuff that's been delivered up to Java 21 that announced they'd be rolling out a fully supported VS Code plugin for Java that should be better than the current language support. It should be out within the next week or two.

Timestamp for the announcement: https://youtu.be/eXCx2hW_xNI?t=1955


Things take time. If you want you can contribute resources to the vs code plugin and the eclipse language server.


What in the java language makes you think it is less suitable to be used without an IDE than other languages?


The fact that IDEs are just unusually smart specifically for that languages relative to relatively dumb editors like vs code, which lack most of the conveniences in the form of auto complete, a wide variety of refactorings, auto fixes, etc. Opting out of all that is not something a lot of people do. Botttom line, you are missing out on so many good tools by not using a proper IDE with Java that it's borderline negligent to opt out of that. It's negligent because you start opting into preventable issues (formatting, warnings, common bug patterns, dead code, etc.) and generally end up wasting a lot of time fixing things manually that you shouldn't have to deal with because your IDE should be doing those things. For example imports are not a thing I ever type manually. Not a thing. Most warnings are addressed with a simple alt+enter, which will typically suggest a usable fix. With and IDE you see those warnings and can act on them.

Kotlin has the same advantage and is developed by Jetbrains who also develop intellij and of course know what they are doing on this front. Support for other languages in intellij is also nice but typically a lot more limited than the support for Java and Kotlin. E.g. pycharm is alright for python but not that much different from what you get in vs code. You get a handful of refactorings and that's about it. Dynamically typed languages are just a lot harder to support with proper tools. Too much uncertainty about what does what or even what types things are.


You describe the great advantage IDE gives. My point though is that without IDE java is basically as good as most other languages without IDE.

I've spent years coding in java daily, most of the time in IntelliJ of course. But there was a time when I had to use for a project a very modest editor, with just basic syntax highlighting. After several days you get used to it and it does not bother you.


Which would put you at a disadvantage relative to other Java programmers. In many teams, that would not be tolerated if you then start committing code with obvious issues related to your poor tooling choices.


How did you jump from "After several days you get used to it and it does not bother you" to "you then start committing code with obvious issues"?

You can't just make up stuff and then blame other people for it...


It's verbose to write and read.

You need an assist for both.


> You need an assist for both.

I don't. Do you?


Obviously GP think it's helpful? Just because you're in the minority that doesn't need IDE or LSP assist writing Java, I think that most people would argue that assist for Java is beneficial even if you personally don't need it and there's no sense in flexing about it.

I personally always use IDE/LSP for Java, even though it's been many years since I've written it, because it helps me deliver business value faster.


We are comparing java with other languages here, not questioning advantages of IDE.

Why people think java without IDE is different than some other language without IDE.

Is java more verbose than, for example, C++?


Exactly this. Who develops in Swift, Kotlin or Rust without ever using an IDE nowadays?


I do.

Or at least, it's a big, big improvement.


And it is not for other languages? What makes Java special here?


Good question. See my earlier comment.


My other language of heavy use is Python. Maybe not writing a Python script from scratch, but at least I can modify a Python script in some basic editor (e.g. GitHub web UI). The same thing will be more difficult in Java.

I cannot judge about Rust and C++ which are mentioned here. I also write some Scala and it is not far from Java in that manner.


I agree, writing Python is easier without an editor than writing Java, Scala, Kotlin, Rust or C++.

This said, Python is often completely unsuitable for jobs solved by Java, Scala, Kotlin, Rust or C++. So I don't think it is a fair comparison.


Class-level imports and lots of classes.


It used to be lots of boilerplate. Like

MyClassType myClassType = new MyClassType()

And then it was nice to use an IDE to help write some of that. Or generate java beans etc.

But with that said, I don't think it's much you need an IDE for, it's more that java enables IDEs to do much more than it can for certain other languages.


You haven't had to declare the type since Java 10.

   var myThing = new MyThing();


Yup, hence "used to", but I could be clearer it's no longer an issue.


My issue with your statement is that you're pretending that this was a recent issue. This hasn't been an issue in over half a decade. Do we point out bugs in libraries from 6 years ago? Are we critical about what other languages looked like then? In my experience, Java is the only one that gets this criticism.


still need it for class members, unlike in some other languages.


Most languages don’t do type inference in “signatures” (function, but also class/struct members), as it would give you negligible benefit, a huge cost for the compiler and is commonly thought of as a bad practice.

Out of Scala, Rust, I believe even Kotlin, none do inference in these places. Even Haskell, which does infer function signatures as well, need explicit type annotation for `data` definitions.


typescript does such inference.

I disagree with you about huge cost for the compiler and benefits are the same as in normal code block: reducing boilerplate.


Typescript’s type system is deliberately not sound though.

In general, there is no type inference available for OOP type-hierarchies as opposed to a more Haskell-like type system, where Hindley-Milner works


I don't have strong knowledge in types theory, but why

class C { a: int = 0; }

can't be replaced with

class C { a = 0; }

? what issues it brings?..


That can. But what about a field that is not initialized there?


obviously you would need to provide type.


That's a thing I don't get. Maybe I am doing something completely wrong, but the vast majority of my time as a developer, I am not typing code. I can afford 5s typing `MyClass myClass = new MyClass()`.


Strange that synchnronization is used at all in lazy-seq

The docs do not mention any synchronization: https://clojure.github.io/clojure/clojure.core-api.html#cloj...


> a Seqable object that will invoke the body only the first time seq is called, and will cache the result and return it on all subsequent seq calls.

To guarantee "only the first time", I suppose you need to have some kind of synchronization at some level.


For multithreaded access yes.

I meant that the docs do not mention thread safety.


"All of the Clojure collections...are efficient and inherently thread-safe."

https://clojure.org/reference/data_structures#Collections

"Seqs differ from iterators in that they are persistent and immutable, not stateful cursors into a collection. As such, they are useful for much more than foreach - functions can consume and produce seqs, they are thread safe, they can share structure etc."

https://clojure.org/reference/sequences

I think it's a fundamental enough property of clojure data structures that it would be redundant to mention it in every docstring.


Thanks, that's convincing.

(why I was in doubt, is because while immutable functional collections that clojure embaces are naturally thread-safe, there is an imperative aspect in creation of a lazy sequence from user provided function, and I was not sure clojure has to provide synchronization guarantees here)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: