Hacker News new | past | comments | ask | show | jobs | submit login

You get quite far with the "final" keyword.



Actually it’s the other way around. There are very good persistent collection libraries for Java but if you are going to ‘update’ then you can’t store them in a final field since you get a new collection object. On the other hand the only thing final about

   final List<Whatever> that
is the identity of the list.

I also think Either and Optional are cancers. Type erasure takes some of the fun away from Either. Before you had Optional you had one problem, you might have a null. With Optional you have two problems, you can get a null AND you can get an empty.

I worked at a place that used Scala and the engineering manager would talk your ear off like an Amway scam person about how much better monads were for error handling than Exceptions. I started working on non-Scala stuff but once they put me on the Scala side I found out that error handling was just missing in most places even though they allegedly did code reviews. It was definitely a frying pan to fire situation relative to Exceptions.

(The time before that whenI coded in Scala I found that people would spend 3 days writing something concurrent with Actors that only used 2 out of 8 cores and was rife with error conditions that could be done in 20 minutes with an Executor in Java.)

In a a parallel universe where LISP was the dominant language, people would be writing essays about how great COBOL and Cold Fusion and PHP are, about what a genius Noam Chomsky was, how recursive descent parsers are a force multiplier, etc.


> With Optional you have two problems, you can get a null AND you can get an empty.

That's not really the fault of the Optional. That's Java adding null as value to every type. Java also allows lists of nulls, mappings to null etc. An optional is just a container that stores one item at most. I do agree that it makes optionals less useful in Java. In Haskell and OCaml they are used essentially instead of null.


Static analysis can catch a `null` being used in a place that wants an Optional. With Optional being fully pervasive in a codebase the `null` concept could effectively be eliminated.


I'd grant that. I'd say the authentic-to-Java approach to the problem is to static import something like a "map" function

   var result = map(x,x=>x.y)
which is equivalent to

   var result = isNull(x) ? null : x.y
where isNull is static imported from Objects.

An approach which is authentic to some other languages is to consistently used a list with 0 or 1 members instead of optionals.


"The time before that whenI coded in Scala I found that people would spend 3 days writing something concurrent with Actors that only used 2 out of 8 cores and was rife with error conditions that could be done in 20 minutes with an Executor in Java"

Sounds like you were working with some folks that were just learning the language/idioms (which is admittedly a big hurdle).

I haven't used actors in a very long time. Simple future composition and reactive streams get you very far, at an absolute fraction of the code size and complexity of the equivalent vanilla Java approach (ie: not using Rx).


That sounds very close to a "No True Scotsman" type fallacy. I've done a fair bit of consulting in the past working with Scala, and my experience closely matches the one described in the grandparent post - the issues happened with veterans more than newbies in my experience (Although that's a function of mostly working with veterans and few newbies)


I have seen junior and senior devs (and myself sometimes) struggle with fancier asynchronous trickery. That's true, but I think it's shortsighted to write off that effort as compared to "just using executors" (whatever that means exactly).

For me there was a lot of learning (that often just felt like grinding), and I can confidently say that I'm leagues more productive than trying to mimic this with low level vanilla Java primitives.

I'm sure this would also apply with go channels, async/await, etc. Raising the bar of abstraction in this case can be valuable. As compared to something really high leverage like reactive streams it's just going to take a ton of code and be far less flexible in a naive approach (in most cases).

I've seen this same pattern with others. Is it worth the investment of time to get there? Not sure, maybe Go is a better set of tradeoffs for most, but I wouldn't go back to straight executors, locks, and the rest of the Java 1.5 concurrency offerings (which is what I thought the OP was saying).




Consider applying for YC's Summer 2025 batch! Applications are open till May 13

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

Search: