Clojure is brilliant in the support of dynamic dispatch at runtime.
The refined design of their collections is a proof of their support for functional approaches.
I am not convinced that dynamic inheritance and protocols promote the maintainability of software products.
Java is slowly moving to improve their support:
-
Switch expressions are now more functional.
In Spring 2022, deconstruction of records, objects, and arrays is still not available.
-
First class citizen status for functions is still ongoing.
You still do not define the implementation of a virtual method using the lambda notation or a method reference.
I agree it is a detail.
But it is a signal if you want to truly support functional approaches.
-
Nice is the effort to improve the collections.
The sequence interface would improve the legibility of the standard collections.
It is still a hack that an unmodifiable collection throws an exception if your code calls a modifier.
It is time to introduce an unmodifiable interface for the various collections.
Groovy is awesome in how operator support enhances the legibility of the source code.
The implementation is syntactic sugar.
Java libraries are the best of breed.
Backward compatibility and static type checks are immensely helpful for enterprise applications developed over decades.
You do not want to throw away such a huge investment.
I like properties and the elegance of grouping the declaration of the field with the methods.
I am still not certain it makes the code quite more legible or maintainable.
If you want to write a functional code with immutable objects, the availability of a with construct is a huge improvement.
Functional programming with sequences is well-supported in all three environments.
Clojure has the edge.
The language is dynamically typed and provides sequence handling for all collections.
Java is a statically type language.
You need first to convert a collection into a stream.
Easy to do, but you have to write the code.
And as an engineer, I truly acknowledge the performance edge of Java against Clojure or Groovy.
Newer approaches based on GraalVM should close the performance gap in the future.