Originally published at deepu.tech.
Being a polyglot developer is fun. You are not married to a single language/ecosystem and you have a diverse tool-belt to choose from based on the issue at hand. But still, you are going to have favorites based on your experience with different languages and their ecosystem.
In my career, spanning 11+ years, I have worked with many programming languages. The first programming language I encountered was Basic when I was in school, but I won't count that since I didn't pay any attention and I didn't understand it back then.
Later when I was in college I had a mandatory computer science class, I was doing Electrical and Electronic Engineering, and there I first came across C, C++, and Java. But again It was just basics and I wasn't very interested and I just studied enough to clear the paper.
I became quite good at Java and JS and really was enjoying working with those and If you have asked me back then, I would have said that Java and JS were the greatest languages out there.
A few years ago when Golang was all the rage, I moved to a project that was built in Go and hence started looking into Go. It was extremely easy to learn and I really liked working with it (for a while).
Rust was quite new at that point and I wanted to try it out but got around to it only a year later and I was in love with it.
In the past two years, I also worked with Kotlin, PHP, Ruby, and C# as well occasionally. But I wasn't very impressed with Ruby and PHP.
So without further adieu, these are my favorite programming languages in order.
Rust is currently my most favorite language. It's so much fun to work with and I love the challenge of rethinking how you write code. You know, as they say, it sparks joy when you work with it. Rust is truly a modern and powerful programming language.
Rust would be my go-to for systems programming, embedded, CLIs, OS tools, WebAssembly, and so on. I guess the only place I won't use Rust would be serious monolithic web application development as the ecosystem is not mature for that yet.
I wrote in detail about what I like and dislike about Rust in this post, but I'll summarize it here for the casual skimmers.
- Safe by default: Rust is memory safe, thread-safe, type-safe, and null safe
- Zero cost abstractions: Write in any programming style without worrying about the added performance penalty
- Awesome concurrency: Great support for multi-threading, parallelism, and asynchronous programming
- Great tooling out of the box: Cargo, Clippy, Rustfmt, and so on. It's the best tooling ecosystem I have come across. Testing, building, bootstrapping, benchmarking, linting and more included out of the box.
- Immutable by default: You need to declare mutable operations explicitly
- Built-in functional programming abstractions: Monad like iterators, optional, chaining, and so on
- Macros: Powerful metaprogramming that can be used to define custom language features, code reusability, and so on
- Excellent community: Fast-growing, active, and really supportive community
- Superfast, as fast as or sometimes even faster than C/C++
- No heavy runtime: No garbage collection and so on. There is a very small runtime for panics and stuff, but IMO it's negligible
- Excellent language features: Pattern matching, generics, iterators, traits, expressions, and so on
- Hands down the best compiler out there. You have to try it to appreciate it.
- Fast growing and being widely adopted: Rust is going places. There are a lot of big names(Google, Microsoft, AWS, Apple, and so on) adopting it and hence cementing its place. It's also finding footing outside of systems programming like embedded, web assembly, web development, game development, and so on. Once the ecosystems for different use cases mature, I see great potential for Rust to be a great general-purpose language without any major compromise.
- Native images: It's so easy to build native images with Rust, no special setup required. Cargo supports building for your favorite platform out of the box.
- Complexity: Being an amalgamation of many languages, Rust does feel more complex than many other languages. I especially would have preferred to not have multiple ways to do the same thing.
- Learning curve: Rust is not the easiest language to learn, especially if you are a beginner or if you are used to working only in one language like Java, C#, or Python. But if you are polyglot and already familiar with a few languages like C/C++, Java, TS, and Go, you will feel quite at home with Rust. There are some advanced concepts like borrowing and lifetimes that take some getting used to and practice to grasp.
- Ecosystem is not mature enough for many use cases. I would love to use Rust for web application development but the ecosystem for that is still very young and you are gonna have a hard time compared to something like Java or C#
So if I would start my own company with a web application as the product, I would 100% go with JVM on the backend with either Java or Kotlin, and of course I will build it using JHipster.
If you like Java, it's hard not to like Kotlin. It feels like a modern version of Java and building Android apps using Kotlin was a nice experience. Unlike Scala, Kotlin doesn't go overboard with all the complexity and implicit stuff.
I might choose Kotlin over Java if building a new web app and if the team has experience with Kotlin.
Also, Java is close to my heart as it's the programming language that jump-started my career.
Here is what I like and dislike about Java
- Ecosystem: The biggest strength of Java is its ecosystem. There are great frameworks and libraries for everything you can think of and most of these solutions are extremely stable with a lot of community and support. In reality, the ecosystem is whats keeping Java popular and growing.
- Experienced community: Java has a very mature and experienced community so even if you are a beginner there is a lot of resources to help you
- Great tooling: There are a lot of great tools out there for Java. IDEs like IntelliJ, Eclipse, NetBeans offer some of the best developer experiences, and build tools like Gradle and Maven are so powerful and feature-rich. There are also profilers, linters, and so on.
- Built-in functional programming abstractions: Monad like iterators, streams, optional, functional interfaces, and so on
- Fairly easy to learn: Java is not very complex and hence is fairly easy to learn and get started even with its boilerplate.
- Boilerplate: Java needs too much boilerplate. There is no nice way to say this. Compared to other languages in its league, Java feels too verbose. Lambdas have made it more digestible but there are other JVM languages like Kotlin or Scala that have got this part right. I really wish Java gets there one day where you don't have to write 20 lines of code to read a file.
- Not so modern: Language features in Java are, let's just say it doesn't spark joy, it's improving but if you are used to few other languages, then there is a lot to wish for, and compared to its peers Java feels old even though its just as old as JS, Ruby or Python
- Baggage: Java has great backward compatibility but that also means baggage. there is a lot of such baggage in Java and it's holding the language back in my humble opinion.
- Virtual machine: JVM was a great idea when Java was introduced as portability was not easy back then but in today's IT landscape containers and native images have made portability easy and that makes a Java Virtual Machine redundant. JVM still provides a lot of valuable features but it also takes up resources and space whereas languages like Go or Rust can just build tiny native binaries that can be deployed using docker to get better performance with less resource usage than a Java app running on JVM.
TS/JS is still my go-to for quick scripting and building client-side apps and mobile apps (ReactNative/PWA)
I wrote in detail about what I like and dislike about JS in this post, here is the summary
- Flexible: The dynamic nature of JS/TS makes it extremely flexible and powerful. It's also very forgiving language. If you know what you are doing, there is literally nothing you cant get done. Of course, the flexibility comes with its own price.
- Ecosystem: JS has a huge ecosystem with a lot of libraries and frameworks. You will find anything you could imagine as a library. The ecosystem is so big that it has started to become an issue in terms of "yet another framework syndrome".
- Asynchronous programming: JS has one of the best ecosystems for asynchronous programming. It's so easy to write async code with Promises and async/await and it has become the de-facto way of programming in JS these days.
- Great tooling: JS has great tooling, thanks to NodeJS and its ecosystem. IDEs like VS Code, Atom, Webstorm, and so on provide great JS support. There are also so many wonderful tools like Webpack, Rollup, Jest, and so on.
- Functional programming: JS is multi-paradigm and has a lot of support for functional programming. It's a great fit for functional programming.
- Easy to learn: JS is a simple language to learn and get started. It's one of the most beginner-friendly languages and communities out there. Of course, there is complex stuff in JS but you don't need to know that to get started.
- NodeJS: NodeJS was the best thing to happen for software development. It not just revolutionized the JS world but also inspired other languages to take note and be more developer-friendly and build easy-to-use tooling and ecosystem. You can see this inspiration in Rust, Golang, and so on.
- TypeScript: TS is another best thing that happened to JS. It provides an answer to a lot of JS issues that bother people and makes it possible to use JS in a more developer-friendly way on a huge codebase.
- Fragmentation: This is the biggest issue with JS. There are standards and there is vendors and that's the perfect recipe for disaster. Most of the time a JS developer spends used to be to make it work across different browsers and platforms. The demise of IE has made this better but hey I heard Safari is the next IE so there is that.
- Error-prone: This is the side effect of being too flexible. JS code is extremely error-prone and unmanageable in huge code bases. TypeScript makes this much much better but still, it's so easy to shoot in your own foot with JS.
- Framework overload: Too many frameworks for the same thing, too many libraries for the same thing, and libraries for doing extremely trivial stuff like left-padding :( Competition is good but IMO what we have in the JS ecosystem is just too much. It causes mental drain and unnecessary fragmentation in the community.
- Over-engineering in the ecosystem: I have been doing JS for over 11 years now and I'm noticing a clear trend of over-engineering in the ecosystem. Look at the JS build tooling for example it has been over-engineered to the extend that setting that up feels like a project in itself.
Go is the simplest language I have worked with and the easiest to learn. I like Golang for quickly putting something together and Go code is quite easy to read.
But I would choose Rust over go for large codebase since Go becomes annoying due to its limited features after a while especially on large codebases. IMO go is still ideal for building small system utilities and microservices.
I wrote in detail about what I like and dislike about Go in this post, here is the summary
- Simplicity: Go is extremely simple. You could technically learn it in a day or two. It's easy to get started and be productive in Go. It's also easy to read and debug as there is only one way of doing anything so you know what is going on without having to ask the person who wrote the code. It's the easiest language for beginners as well.
- Built-in tooling and style guide: Go provides built-in tooling for all the basic stuff like dependency management, testing, build and so on. It also has an opinionated formatter that saves a lot of time.
- Goroutines: Goroutines are awesome. It's so easy to use and intuitive and the best concurrency experience you can find.
- Native images: It's so easy to build native images with Go, no special setup required. It supports building for your favorite platform out of the box.
Simplicity: Go's simplicity is really nice when you are getting started but it starts to feel like an annoyance once you start writing more Go code. If you come from another language, you soon start to yearn for features like generics, error handling, default values, and so on. Keeping code DRY is a challenge in Go due to the lack of generics. IMO Go would be a great language if it had generics. Also, I dread writing
if err != nilin Go.
- Boilerplate: Side effect of Go being too simple. In large codebases, you would be repeating stuff like finding an item from an array or map so many times that the boilerplate is just too much after a while.
- Implicit interfaces: May it's just me. I don't like implicit interface implementations. It just feels wrong and confusing to me.
These are my personal favorites among programming languages and doesn't mean the likes and dislikes would apply to anyone. make your own conclusions but do use the language before making a judgment about it.
In today's IT landscape, being a polyglot developer is becoming a requirement. And personally, I believe that being a polyglot makes you a better programmer and software engineer. I previously wrote about how to be an effective polyglot developer, do check it out if you are interested.
If you like this article, please leave a like or a comment.
You can follow me on Twitter and LinkedIn.
Photo by Peter Herrmann on Unsplash
Top comments (20)
JVM is quite misunderstood. It provides much more than "portability". Take a look at benchmarks binary trees. It easily beats even Go. Why? Well JVM is also JIT or more accurately it contains JIT. This one can kick in after some time and provide such optimisation than no developer would think of at the time of writing the code. It changes your code based upon "experience" of usage. Now cold start is something else but having underlying "machine" that optimises code for you is quite nice for long running services. Cloud is not just services going up and down. Some work loads actually have "never-ending" services and that's where this is better than pre-complied code so to speak. It's not best it's just usefull in a lot of cases as "benchmarkers" usually like to do a quick test instead of checking process in real world running at least a month.
Ya sure, I know that and thats what I mentioned as providing other stuff (may be not the best way to state that) but still the real reason for having the JVM is redundant and it can become much more light weight and less resource intensive with only the useful stuff like JIT, GC etc IMO
It's all a question of trade-offs. Java was designed at an age where developers thought that everybody would have machines with infinite computing power and infinite memory. On those kind of high-end systems, Java feels like the natural choice for complex projects.
However, the sheer overhead of Java is insane (not to mention dealing with dependencies...). I have a 10-year-old server with a quad-processor and 16GB of RAM which has reasonable performance, so long as it runs anything that was compiled (perhaps with the notable exception of PHP, which is a lightweight language, also with just-in-time compilation). Launch anything that uses a JVM, and bye-bye server — it will basically only run that single Java application and nothing else (granted, Ruby on Rails is almost as bad as Java).
Personally, I think that the time of Java is over. It's just due to sheer inertia that it's still being used and actively developed; that, and the fact that computer programming teachers still insist in putting Java in their curriculae, simply because it claims to be the programming language attracting the highest number of programmers. But this is a self-perpetuating illusion: there is a huge Java community because everybody was taught Java at school.
I was very excited when Java first came out, being a fan of C/C++, but feeling frustrated that there were so many portability issues back then. Java seemed to be 'future-proof' — and when you could embed it inside a web browser, it was a dream coming true. Finally, at last, you had a programming language that could pretty much be compiled once and run everywhere!
That basic assumption was insanely successful (also, it helped to have Sun backing it up — a company that did so many wonderful things for the computer industry and who got such a tragic end, being ripped apart by Larry Ellison...). The problem was the trade-offs it came with. These have naturally been addressed over the years (decades?) but it's clear today that there is a limit to how far you can push Java.
Basically, these days, Java is the Kim Kardashian of programming languages: it's famous because it's famous.
Then again, I'm utterly biased against Java, mostly because I had to maintain servers that run insanely large Java applications, consuming all resources and then some. Enterprises deploying Java extensively basically trade off developer time for system administration time; developers are allowed to pretend that they still have infinite CPU and infinite memory to run their badly-coded applications, leaving the fine-tuning to system/database/network administrators — but with Java, there is a limit on how much you can do to speed it up...
As you said you are utterly biased against Java. So I quite disagree in many ways with JS being replacement due to many issues including security and the way Node works. Java (mainly) uses Java modules without extra code for specific platform. Go looked great but it will take time to replace ecosystem which is by many Java devs actual reason why it's famous not the "Kim Kardashian" nor any professor putting it in the class. I was bombarded with MS tech in university and I still avoid those. So logic that it's being pushed is not relevant. Thing is you can try to kill it out and downgrade it's value but the quality of those libraries and frameworks is much better than JS ones. Some of us dislike forcing "rules" like never ever mutability and such so Go , Elixir and others won't hold water. I don't have problems with JVM because services I build are not bloated and I avoid reflection based tools. Example I use Micronaut instead of Spring when performance is important. I'm still waiting for a language to replace it in a way that libraries are easy to use but as well written just i that language. Node has too many C and Rust tools with interface to JS. PHP and python as well can't run specific modules on Windows because underlying implementation was a compiled language. Go looks nice yet you need to compile it many times for different platforms. It's about having seamless process of writing the code on one machine and working the same on the server. Regardless of that all this talk was about Java instead of JVM which is different. Kotlin, Scala, Groovy... A lot of tools from Apache like Kafka, Pulsar... Thing is there's too much to replace to kill it off. Just like PHP
You are absolutely right. Also can't stop laughing. This is a gem 😂
IMO java is a chicken and egg situation. It has the most mature ecosystem because it is one of the most used lang and it is most used because it has the most mature ecosystem. I'm just waiting for Rust's web dev ecosystem to mature, after that there is no looking back 😉 alternatively if generics finally happen in Go, that is viable as well
If generics get good in Go I would actually consider switching to it fully. Rust is a bit too much for SoA or microservices for my taste. Go looked easier but I'll give Rust another look. However I don't believe community would allow some changes (functinal devs are like class based devs that thought they are oop). Scala looked interesting however I didn't have time to switch to it but for you it might be again JVM. Unless you're up for native images with Substrate (Graal). 😁
Ya. Go could be a good compromise between Java and Rust. Rust does take some getting used and IMO harder to go back from once you are used to 😉
A little bird told me that generics are on the queue for Go 1.17... stay tuned.
Hint: take a look at the source code for the official Go distribution. Here is a nice little pearl: go.googlesource.com/go/+/refs/tags...
You can also see the same file on GitHub's mirror. Notice the difference? On Google's own repository, files ending in
.go2are properly syntax-highlighted; GitHub still doesn't know what to do with those files...
That is absolute nonsense. I don't know what Java software you ran. But I've run enterprise java software processing thousands of complex orders from an eretailer an hour with less resources than that. That software wasn't even optimized for that process.
If there is anything these days which assumes infinite CPU and RAM, then it's the whole Node/JS world. You can't even "compile" a basic Angular application on a dual core node with 1GB RAM.
Java carries around a lot of baggage from the early years, which they cannot really get rid of unless they want to break compatibility. But JS (and thereby by extension TS) carries around an absolute nightmare of legacy. A legacy which is unfixable. TS might have been able to fix it, but you simply can't have a pure TS application as there is still of JS-isms used by various packages (and even JS dependencies you cannot get rid of.)
PHP was given a horrible reputation because of bad language decisions. JS as most of the same issues, and more.
Well, to be honest, and as I've mentioned, I'm not that fond of JS myself. A language that implements closures simultaneously with classes without encapsulation has very serious conceptual errors. I read somewhere that encapsulation in JS classes is on the list of upcoming capabilities; but I'd also bet that closures won't disappear, since that will break a lot of JS code, and, on top of that, they're a bit more efficient than classes for singletons... anyway, that's just one of the many, many details of the kind of baggage that JS carries as legacy which will plague developers for decades. I just mentioned that JS has a reasonable chance to 'replace' Java mostly because you can have both JS on the front end (a Web browser) and on the back end as well: you just need to be proficient in a single language, use a single toolset, and so forth. Ironically, it was during those days when Java applets on browsers were popular that Java showed its biggest promise — a way to close the gap between the front end development and the back end. But that came at the cost of an utter waste of resources on the browser side of things... while JS seems to be better positioned to deal with that.
Still, I concede that JS does, indeed, carry around way too much legacy, and very likely because of that I was wrong in my belief that it would ever replace Java at some point. After reflection, I think you're right: JS does way too many things wrongly, and the future will bring more complexity while dealing with legacy, not simplification that might get a compiler to produce more efficient code.
Legacy, indeed, is a nightmare to manage. I'm personally fond of PHP, after hating it with a vengeance for a few years — way before we even had classes in PHP, much less the plethora of goodies that are available today. However, I totally agree that there were lots of bad language decisions; and now the core developers are effectively forcing developers to start tidying up their code, or it simply won't run under PHP 8.0. I think that PHP 5.6 was a turning point: a clear message telling PHP developers that the days of sloppiness were over, and a 'last chance' to read all those warnings in the logs before moving on to PHP 7 and beyond...
But the truth is that I started to appreciate PHP because of lazy programming! Here was a language that allowed you to write code very quickly, without even bothering with boring details such as declaring variables. This approach works well while a language's syntax is very simple — which was true for PHP in the early days. I mean, if you have just a handful of types, all of which can be converted into each other, well, then you can allow lazy programming. The problem came only when the PHP core developers wanted to add all those nifty features that were available on other programming languages. And I agree that JS followed the same path (thus, TS). Actually, we ought to have 'Typed PHP' at some point in time, too; on the other hand, it looks like PHP is moving in that direction by leaps and bounds...
As for Java, I'm still sticking to my first point: I certainly believe that some people can get good enough performance out of it, and possibly keep all their dependencies in order (using Maven or whatever tool is popular today), therefore combining the advantages of a complex language designed to tackle complex problems with a predictable development pipeline ('predictable' in the sense that you can rely that, during, say, a five-year project, you will still be able to run the code you started writing, while still keeping all those hundreds or thousands of dependencies up-to-date with the latest security and performance patches).
But my comments were based on the assumption that it's next-to-impossible to accomplish that — an assumption grounded on my own experience, which, granted, is extremely limited, and was uniformally bad. My worst nightmares actually came from Java applications that people specified as the 'best' choice because, well, Java works universally on any device that implements a JVM, right?... That's what it says on the box (see the comment by @greenroommate below: the selling point of Java has always been 'compile once, run everywhere'). In practice, there hasn't been a single Java project that I had to deploy which hadn't some impossible-to-resolve dependency issues (Maven or no Maven...); and when complaining to the developers that their application didn't run under, say, FreeBSD, they would just shrug and comment that they never recommended deployment on anything outside the Windows or Linux worlds...
I certainly understand that there are many reasons for such choices; if 99% of your market runs their Java applications in a very strict and controlled environment — a very specific platform, with precisely defined characteristics such as the kind of system libraries that have been installed — it's reasonable to assume that if you're attempting to run it on anything else will not work. But that defeats the whole purpose of using Java in the first place.
Now you can argue that the same is true for all the other languages (and especially so for the natively compiled ones), at least to a degree, and I would certainly agree with you on that, but that's not really the point. The point is that a regular human being will be always hard-pressed to get a Java application to run efficiently and with adequate performance on whatever platform they happen to have. In other words, the time eventually saved by Java developers in producing cross-platform code in the first place (not needing to worry about eventual differences between systems, since they write code to be compiled and run under a JVM) is then spent by those who need to deploy such code on a platform that is theoretically supported (in the sense that there is an available JVM for it) but in practice never works, or only works by taking up a huge amount of resources, or requires a complex setup which will only work for any Java application running on that particular system to the exclusion of anything else; my 'bad' experience with Java comes from all those cases, happening over and over again, and which even seem to get worse over time (but I admit that this can be just my perception).
By contrast, other developers do not even bother with 'cross-platform code' — they just ship a Docker container. I have my issues with the whole Docker concept, but that's another story. The point is that if you 'need' a very specific instance of a virtual machine to run your application, then why bother with using a so-called cross-platform language, when all you need is to develop your application in whatever language and environment you prefer and simply put it inside some sort of virtual machine (such as Docker) instead?
On one hand, I never benchmarked such a trade-off, between writing something in Java and expecting it to run everywhere, or writing it in whatever language you prefer, and get it running under a Docker container instead. Maybe a Java application will beat anything else that requires a virtual machine (or, if you prefer, perhaps the JVM is the most performant of all VMs out there). I simply don't know, I just have personal (and therefore subjective) perceptions based on my (limited) experience.
Some years back, there was a discussion around a specific application I've used which had been painfully ported from Windows to macOS, running natively on both, at the cost of thousands of development hours, plus the extra hours of ongoing maintenance to keep the code in sync. This was not a simple application using, say, Qt, or some similar cross-platform toolset/framework. Rather, everything had been done from scratch, in both platforms. There was a small contigent of Linux users who argued that they would also like to be able to run that application as well; and if it had been succesfully ported to macOS, then it would be very likely much easier to port it to Linux as well. It wasn't, and for many years, the developers refused to even consider to 'waste' more development time just to create from scratch a third codebase. Ironically, or perhaps not, at some point they actually did release a Linux version... but this was 2007 or 2008, and the iPhone (and the first Android phones) had just been launched, and, consequently, people were asking when they would have a native version of the application on their iPhones as well, even with limited functionality... we're still waiting for that in 2021!
It might be argued that if the application had been developed in Java (and not C#/Objective-C), it might have been much easier to port it to whatever technology becomes fashionable. It's not as if that company's developers did not know how to develop in Java — they most certainly did! — but rather because they were afraid of whatever performance hits they'd get from that approach, and, more importantly, they knew it would be a very hard task to give reasonable tech support to next-to-clueless new users, teaching them how to properly configure their Java environment just to run that single instance of the application.
Back then, all I could remember was the hard lesson given by Triple-A game developers: if you wish to avoid performance issues, just statically compile everything in C/C++...
Now I can see that many issues you had where history related. You mention docker but then also not working on FreeBSD or such. Most of these things are not there anymore given docker, fatJars and recent movement towards using less reflection but mainly new versions of Java and JVM. I don't really understand people dragging old issues. It's like saying C# is bad because you need Windows yet here we are in 2021. So yes there was a lot of bad things in Java libraries, for example I personally can mention writting desktop app in Java but for usage with MS SQL Server 2008. Yeah, .jar libs had DLLs inside of them as a driver which meant Windows only. So is that JVM not running or people doing dumb stuff? Why, write, put a DLL and do a call to native driver? That's what was wrong.
But to put it in perspective, node modules are heavier than the black hole and Node sucks up way more resources on big processing where data is not 2KB JSON but 1GB and such. It's simply incorrect that it drains nore resources than Node or such. Maybe true in simple cases with smaller data. There's a use case for everything. They also, as I said have way too many ports from rust and c. So does Python, so does PHP. So bashing Java for it you bash those languages as well. As to why it's hard to accept that this is the case with others but easy to hate Java beats me.
I have enormous amount of porting problems today with PHP apps and as a solution we're rewiring it into something that can be put in docker easily. And yes some of it is Java. And first thing to notice is usage of 1.8 while we're in te year od 17 being stable soon. Why do people do this beats me.
Overall, there is a lot of porting issues with some Java libs as I explained, and even Go might be better here, it's really unrealistic to ignore same problems you mentioned with other languages. Again I had those with Python, PHP, and Node. Java's main selling point might have been "write once run anywhere" but it's 2021 and we need to compare todays version and point of view.
I really like that someone is able to have a discussion of it and I'm not defending Java as I have a lot of complaints about it as well but JVM is at the bottom of it and it's resource consumption. I just don't like being too unrealistic and ignoring that a lot of things have same problems so I comment.
Almost nothing you said about Java is true.
Well, at least it's true that its the most taught programming language at college/university level... or isn't that true, either? (there is still hope)
On the other hand, I might be an extremely unlucky person — just got the chance to tweak/install/maintain the absolute worse of the worse among Java applications out there. It's true there weren't many; however, all were insanely bad, and subsequent releases even made them worse. But there are some niche markets where you have no other option...
Perhaps if I were much luckier and only found the best Java examples out there, I might have a completely different opinion...
It's not about luck or particular app.
'a few years ago when Golang was all the rage'...
... well, I'm writing this in 2021, and as far as I can see, Go is still 'the rage'! :-)
Not as much as it used to be 😉
Wish there had been one pure FP language in here such as Haskell, OCaml or Clojure.
That is because I don't believe in pure FP 😉
haha fair enough I guess. Is it because you find it to be impractical?
Yes. I like to use the paradigm that works best for issue at hand. I like to do functional programming when possible and imperative/procedural/oop when necessary. Thats why the languages I like are multi paradigm languages. I like to use good things from all paradigm. For example in Rust I use monad like constructs (iterators, optional) and chain function pipelines all the time. But I also make use of traits (I know its not OOP, but the style is bit similar IMO) and I do imperative when functional code is too convoluted to write in some cases. Being tied heavily to one paradigm is restrictive IMO. Also in languages other than Rust/C++ you pay a price for doing heavy functional programming, while it might be negligible for most use cases, it would make a difference in performance critical use cases. For example I would always write for loops instead of recursion when performance is important (Except in Rust due to zero cost)