This is an effort to document the difficulty I’ve faced in choosing a programming language for my toy projects. To dispense with the obvious suspicions, I will clarify that I am not a perfectionist; I neither expect my language to be the fastest, nor the neatest. Yet I have found that a few traits of my chosen language tug incessantly at my attention, which never keep me far from the all-pervading question of whether I’m making the best choice or not.
For this article we will assume that I haven’t conquered my urge to second guess myself, and to go back to the drawing board for no reason other than the call of analysis paralysis. In other words, we will bypass the obvious advice to shut up and just build—however correct the advice may be—in favor of pursuing a perfect language for its own sake.
Scala
Pros:
- Memory managed
- Very strong static types
- Monads everywhere
- Null safety
- Pekko’s Actor model
Cons:
- Dead in the industry
- Cannot achieve hard realtime
- Unhappy web app experience
- Zio is ugly
- Cats Effect is ugly
- No easy web or mobile experience
I mention Scala first because it comes as close as I can imagine to a perfect language. The type system is so expressive that entire domains can be conveyed as a tapestry of Traits and Interfaces, and when combined with the Akka/Pekko ecosystem, entire behaviors were easy to enshrine into code. Combined with a reasonable review policy discouraging the overuse of DSLs and Implicit conversions, a Scala codebase avails itself as an absolute pleasure to read and modify.
My experience using Scala 2.13 at Trumid was so enjoyable that I despaired having to one day regress to any other language.
That brings me to the great tragedy of Scala. It’s a dead language. Notwithstanding the stalwart optimism of those over at r/scala, it is indeed the case that Scala never quite hit critical mass, and the window of opportunity for it to take off has passed. All that’s left of its perennially early adopters are some rare industry holdouts and tinkerers in academia.

https://www.tiobe.com/tiobe-index/scala
Should you ask why the popularity of the language matters, I have no satisfactory answer to offer. My intention in choosing a language for my toy projects is in a way more a meditation on the language, than the project for its own sake. Hence I am not satisfied in hiding away in a distant cave, furnishing a growingly esoteric set of skills. I want mastery of the ugly details of this language to materialize to my benefit out in the open, and Scala is not up to that task.
Typescript
Pros:
- High demand in the industry
- Memory managed
- Very easy full stack web apps
- React & Node
- Strong (compile-time) static types
- Default parameter values
Cons:
- Not fast
- Nullable objects
- No viable gaming story
- Questionable job quality
On the subject of industry viability, it would be remiss not to speak of Typescript (and by extension, Javascript). It’s true that this is the most in-demand of all languages. No one can contend with the dominance of “HTML”, “CSS”, and “JS” at the top of language rankings that scrape job postings, because most of those “HTML” and “CSS” mentions are associated with Front End developer openings.

https://survey.stackoverflow.co/2025/technology
That Typescript is not thereby the winner among my desired programming languages is the exception that proves the rule: maximizing on industry marketability isn’t the end all be all. I want to enjoy writing programs in this language, and more specifically, I want the option of performance and gaming available to me.
In playing with Typescript code, I am ever aware of the strangeness of prototypical inheritance, of how any class can have any method attached to it along the chain of my imports. I am aware that the program runs on a single thread. But none of these quirks weigh as heavily on my mind as the foreknowledge of the limits of the language. Should I ever want real performance from a backend, I would be shooting myself in the foot by sticking to any language that compiles down to Javascript. The absence of any serious gaming pathway in the Javascript world attests to this limitation.
Rust
Pros:
- Fast, low memory
- Borrow checker
- Very strong static types
- Null safety
- Null pointer optimization
Cons:
- Niche in the industry
- Borrow checker
- Painful prototyping and refactoring
- Lifetime annotations
- Game library (bevy) is unergonomic
- Ugly syntax
Rust is the salad that I forgo in favor of the pizza.
Compile-time memory safety through the borrow checker is a fascinating concept. It reveals to me my long-learned cognitive shortcuts. Spoiled rotten by languages with managed memory, I don’t often think about when a variable exits scope and can be cleaned up. I don’t ever ponder the implications of self referential data structures and the nightmare that comes with trying to clean them in parts or their entirety.
I feel guilty for not using Rust when I have learned it well enough to leverage. I feel guilty for giving up on the language every time I get bored of lifetimes and of its async linguistics. I feel guilty for choosing slower and heavier alternatives when I could wield something stronger.
This begs the question of whether there is something else wrong with the language, some undiagnosed illness that causes it not to be my first choice. It would be all too easy to find one of many available criticisms of Rust; from its messy packages, to its strange in-place tests, to its lack of serious industry adoption. But I find that none of these reasons are strong enough to not choose Rust. Therefore, I keep Rust to the side while not out of reach—a side of salad—for one day in the future when I’m ready to take that leap.
Java
Pros:
- High demand in the industry
- Memory managed
- Easy full stack web apps
- Quarkus & Vertx for performance
- Static types
- Gaming library with libGDX
Cons:
- Type erasure in generics
- Cannot achieve hard realtime
- Unless using ugly Java
- Checked exceptions
- Nullable objects
- No default parameters
- No easy web or mobile experience
Java is Old Faithful, the first programming language I used in earnest. As of writing, it appears to be in the top 3 of most demanded jobs in both Big Tech and Finance. It’s also used in every noteworthy name in the industry, from Google to Goldman. It’s very fast, and can reach speeds close to C++ when written for that explicit purpose. More importantly, it’s quick to write, and easy to refactor, an invaluable feature of a language used for toy projects which are prone to considerations and reconsiderations.
But it lives up to the “Old” in Old Faithful. In keeping its valiant promise of eternal backward compatibility, Java has had to tolerate the drunk uncles of previous iterations at every Thanksgiving feast, from its type erasure in generics, its checked exceptions, to its painful absence of default parameters. Yet in other ways it’s too modern, obfuscating mechanisms that I may want to control in the future. I feel a particular shame for relying on Java when I could, ostensibly, have chosen C++.
This blog post serves as evidence to Java’s shortcomings, because if it had been everything I wanted it to be, there would be no reason to hem and haw about alternatives.
As of writing, all these shortcomings are not enough to dissuade me from Java. And in case it needs to be said: these shortcomings are never show stoppers. For now, I will soothe the sting of my complaints about the language by compiling some convenience tools of my own. The ones I’m proud of, I will write about. The ones I’m ashamed of, I’ll write about too.