Hacker News new | ask | show | jobs
by davidalayachew 882 days ago
> Most of Java problems come down to unfortunate design choices in the past. E.g. checked exceptions vs lambdas

Funnily enough, your example has actually supported my point.

They just released a proposal that effectively side-steps the problem of checked-exceptions-in-lambdas. Here is a link -- https://inside.java/2023/12/15/switch-case-effect/

This is still just a proposal, so nothing is hammered out. And we can talk about the merits of this solution. But my point is, by focusing on designing features the way they have, you can minimize intrusion while maximizing the value provided. I think this proposal demonstrates that extremely well.

This proposal allows the developer to maintain all the good parts about checked exceptions and lambdas, while being able to side-step the major downside.

> Don't think like Java is a good example of that, more like the anti-example. Plenty of more sophisticated languages move way faster without negative effects on long term progress (C#, Kotlin, to some extent Scala)

To be clear, when I say long term, I am measuring on the scale of decades. In that respect, I actually don't think your statement is correct.

To give an example with Kotlin, someone (I think Brian) talked about Kotlin's release strategy for features being great for short term, but costly in the long term. Kotlin had record-esque classes long before Java ever got theirs, but now that Java finally has theirs, Kotlin is using an annotation to disambiguate between Java style records and Kotlin style records -- https://kotlinlang.org/docs/jvm-records.html#declare-records.... While this isn't some critical problem on its own, this type of rift growing wider means that Kotlin is going to have to wrestle with how much they want to allow Java representation of concepts to exist in Kotlin. For example, how will Kotlin handle Java's version of pattern-matching vs their own? The 2 are not the same, so you cannot just call them aliases of each other - they have different semantics.

To give another example with C#, there has been a lot of recent discussion about finding potential alternatives to their async-await concurrency model. They cite the level of effort it takes to maintain the async await style code and the costs that come from this. Rust had a similar conversation not too long ago too.

The point I am trying to say is that, I think Java's strategy of play it slow and conservative is actually paying off for them, but on the scale of decades. Some of the languages it gets compared too aren't even that old yet.

2 comments

> They just released a proposal that effectively side-steps the problem of checked-exceptions-in-lambdas.

The main problem of checked exception in lambdas is that Java's type system does not allow expressing statements like "`forEach` throws whatever the lambda throws". Here are two links:

http://james-iry.blogspot.com/2012/02/checked-exceptions-mig...

https://blog.jooq.org/javas-checked-exceptions-are-just-weir...

The proposed syntax puts the exceptions on equal footing with the happy path. Not a bad idea, but irrelevant to the main problem.

> They just released a proposal that effectively side-steps the problem of checked-exceptions-in-lambdas. Here is a link -- https://inside.java/2023/12/15/switch-case-effect/

This is fine but removes only about 10% of the pain of mandatory exception handling inside typical lambda.

Nothing short of making exceptions transparent to lambda receivers will cut it for me.

> Kotlin is using an annotation to disambiguate between Java style records and Kotlin style records

This is inherent risk of building on top of something you don't control. Don't really see this as fair comparison. It's a known design constraint. The only way to avoid it is to not build on top of Java or not adding any features on top of Java.

> To give another example with C#, there has been a lot of recent discussion about finding potential alternatives to their async-await concurrency model. They cite the level of effort it takes to maintain the async await style code and the costs that come from this.

I had a very different take-away. They did PoC with virtual threads and decided it's not worth the switch now and async-await that they have is good enough.

https://github.com/dotnet/runtimelab/issues/2398

> Some of the languages it gets compared too aren't even that old yet.

C# is more than old enough to drink and Scala just had its 20th birthday this weekend :) Java is only 4 years older than C#.

> Nothing short of making exceptions transparent to lambda receivers will cut it for me.

If your wish is to have Checked Exceptions be throwable from the lambda, then I understand your point. Still, I stand by argument, which is that they are actively addressing these pain points, but doing so slowly in ways that minimize intrusion.

> Kotlin

If it's not a fair comparison in your eyes, I'll leave it.

> async await in C#

I'd be more willing to accept your point of view if there wasn't so much discussion online about how painful async await is via color-my-function. And that's ignoring the fact that languages such as Go and Erlang have been garnering a big following, in large part due to their concurrency model and how simple it is.

I have had my share of async await too. I think it's no coincidence that many language designers are looking more and more into moving away from async await, thus prompting these PoC's and experiments.

As for the C# link specifically, I interpreted that to be that they felt the pain of async await strongly, and did the PoC in response. However, the PoC did not play well with their async await world, and trying to change the world to make room for it would be too much of a lift. Therefore, they stick with async. I did not interpret it to be that async await was good enough for them, but rather, that improving async await is the best option available to them for now.

> Age of languages

Sure, there are some languages that are a similar age to Java. But those are the languages where I believe the costs for the decisions they made are becoming more apparent. I already gave 1 example with C#. And I think we can both agree that Scala's design philosophy served as a great learning experience for other languages, but was a poor survivability tactic as a language. It feels like the language is buckling under its own weight.

Either way, I am not trying to say that these other languages are bad. Merely that their design philosophies benefit them in the short term, but show cracks in the long term. Java's philosophy, meanwhile, minimizes intrusion, and thus, allows it to sidestep alot of the problems that these other languages are trying to get out of.