I agree w that, but I think Scala has deeper problems.
It tries to be a better Java and a better OCaml at the same time. This split personality led to Scala’s many dialects, which made it notorious for being difficult to read and reason about, particularly as a mainstream language contender.
Above all, Scala is considered a functional language with imperative OOP qualities. And it more or less fits that description. But like it or not primarily functional languages don’t have a strong reputation for building large maintainable enterprise software.
That’s the quiet part no one says out loud.
It’s like how in academic circles Lisp is considered the most pure and most powerful of programming languages, which may be true. At the same time most real-world decision makers see it as unsuitable as a mainstream language. If it were otherwise, we’d have seen a Lisp contend with imperative langs such as Java, C#, TypeScript, etc.
I’ve always attributed this disconnect to the fact that people naturally model the world around them as objects with state — people don’t think functionally.
Scala unfortunately feels a lot like Perl. Three people write in four different styles.
I mean, that was my beginner impression and at least half of the Scala developers I asked about this agreed. Also I just never found the improvement over Java good enough, that wasn't worth all the downsides. This is even more true with modern Java or Kotlin. Same benefits but it's easier to read, not harder.
> Aggregation is not inheritance, rather a workaround, using delegation
Although the designers of COM had the right idea, they implemented delegation in just about the worst way possible. Instead of implementing true delegation with multiple interface inheritance, similar to traits, they went pure braindead compositional. The result: unintuitive APIs that led to incomprehensible chains of QueryInferface calls.
In general the tooling sucks, which is kind of strange given how relevant COM is on Windows, even moreso since Windows Vista.
It seems the Windows team is against having something like VB 6, Delphi, C++ Builder, .NET Framework, MFC, approaches to COM tooling, just out of principle.
Thus we end up with low level clunky code, with endless calls to specific API like QueryInferface(), manually written boilderplate code, and with the IDL tools, manually merging generated code, because they were not designed to take into account existing code.
Submit interesting unique links and post more substantive comments (maybe add a paragraph or two your previous comment) and you will be able to downvote soon enough. But I don't understand the appeal, when I do it is usually accidental (really easy to do on a tablet)...
I usually downvote comments that are derailing the thread or are so lazy as to feel like a waste of my time to have read.
I'll often upvote comments with opinions that are counter to my own, especially if they are presented in a clear, coherent, or novel way that causes me to think a bit.
It helps prevent brigading and ensures that users have a moment to adjust to the community and its general expectations before being able to participate in community moderation.
If a user cannot reach that low bar after a while, they probably aren't a particularly active or positive member of the community.
Quite similar to manifold-sql[1], which is arguably better integrated into Java than SQLx is into Rust. Inline native SQL in Java is *inherently type-safe*, no mapping -- query types, query results, query parameters all projected types at compile-time.
int year = 2019;
. . .
for(Film film: "[.sql/] select * from film where release_year > :rel_year".fetch(year)) {
out.println(film.title);
}
Because if X ever happens, the note won’t matter anyway, since you will have had to grok all the related code to refactor. You will see this note while you’re refactoring the surrounding code and smirk, “yep, that’s right”, or “no, it doesn’t really fall out that way.” Either way, most TODOs/NOTEs like this just get in the way.
What if these were real, type-safe expressions in Java:
2025 July 19 // → LocalDate
299.8M m/s // → Velocity
1 to 10 // → Range<Integer>
Schedule meeting with Alice on Tuesday at 3pm // → CalendarEvent
That's the idea behind binding expressions — a compiler plugin I built to explore what it would mean if adjacency had operator semantics. It lets adjacent expressions bind based on their static types, forming new expressions through type-directed resolution.