As the author says, these features also come from Kotlin and Scala, and they are immutable objects, abstract data types (via sealed interfaces and exhaustive switches), and require Java 21 with some experimental flags.
It’s rather unfortunate, as Graydon and others from Mozilla Research were extremely open about Rust’s influences from the very beginning, and that really opened my eyes to the wider world of programming language design. You can see part of this living on the current bibliography, but sadly it’s a bit hard to find. As the development team and the community has scaled it seems like it’s been harder and hard to keep this knowledge alive and well-known, and I think this is a real problem.
At the very least, I do really like how the RFCs reference prior art… it’s incredibly frustrating when languages like C++ fail to include this information in their standard proposals.
For an interesting discussion between Greg Morrisett (one of the creators of Cyclone) and Felix Klock (who was an early contributor to Rust), I highly recommend the fireside chat from last year’s ICFP.
As a follow up, I should note that discourse around Rust is far from the only place where this happens, it’s just is very prominent at the moment. Our entire industry needs to be better at teaching new and existing programmers about context and history… even if that requires working against structural pressures that encourage us to portray every exciting technology as springing out of nowhere.
I would have really liked my computer science course to have taught me more about the history of the programming languages and technologies we use. Unfortunately, computing history seems to be very unpopular with my fellow students. I suspect it’s because it’s not immediately applicable to a career. I think that, at least where I’m from, most students of computer science are after a fast track to a lucrative job.
Edited to add: perhaps that’s too harsh on my fellow students; but I do think that most people are primarily interested in what they can do now (because that’s the most immediately practically relevant) and not what has come before.
Yeah, definitely agree. I think this is something that would be great as a first semester class, to provide context for the rest of the course. It’s one of those things that can be painful a at the time, but you look back on with fondness and can really change your perspective on the world (I had a similar art and design history class as part of a graphic design degree).
I think it would be possible to do this as part of introductory programming.
That is start out with simple programs in some sort of Basic as someone starting out hobby programming in the 80s, and work yourself forward in time adding concepts as you go.
Maybe not worth building the whole curriculum around, but could work as a first semester intro to programming schedule.
Kotlin is honestly my favorite language, at least in a practical context (you’ll pry Smalltalk and Common Lisp from my cold, dead, zombie hands). But the fact it comes from JetBrains, who adamantly refuse to implement an LSP, means that using it at high levels of effectiveness basically requires using JetBrains’ IDEs. I don’t mind needing Fleet or IntelliJ when I actually need to go all-in, but lacking a reasonable way to quickly slap together a Kotlin script with autocomplete and whatnot from Helix or Emacs or whatever does grate after awhile in a way that e.g. F# on .NET Core does not.
Yes, there are a couple of third-party LSPs for Kotlin, but neither of them have been good enough to let me do basic Android development in Emacs. And given how badly Android Studio runs on the hardware I actually own, that strongly discourages me from developing for Android.
Many years ago I wrote a web crawler in scala. The actor library in the standard Library allowed me to write a single script and execute it with the need for dependencies. It loved the fact that it had a clean and compact syntax. And with the actor model ready to use of box, it was easy to implement concurrency models.
The crawler would run well, but after an hour or so, it would reach a deadlock state. I couldn’t figure out what I was doing wrong. I searched everywhere, went to the community to ask for help but in the end I gave up as I found no solution. Some 5 years or so after, inred online that the actors library from the stdlib was going to be retired and among the reasons, there was a bug which was exactly the problem I had.
Never again. I have used 20+ programming languages professionally for decades and never once I have stumbled upon a bug on the programming language that directly breaks the main functionality like this. Even in new experimental languages.
I simply lost the trust that it works. No way I am touching it again.
I also think they suffer for the same problem as Perl. Too many ways to do simple things, to the point that the language becomes cryptic.
It was MANY years ago. I don’t even have the source of that project anymore. The crawler, I wrote it 12 years ago. If you look into the retirement of the Actor library announcement you might be able to navigate to it.
I believe that was perhaps 5-7 years ago or so.
Unfortunately, we’ll just have to take your word for it that Scala is full of bugs that ‘break the main functionality’ (despite your admission that the buggy library itself was removed) ;-)
I didn’t said it was full of bugs. I mentioned one bug. I have never encountered another but in a programming language. When I am writing code, and something doesn’t work, I never ever for a second assume that it could be an error in the programming language. I think that that sacred frontier is important. We have to be able to assume a reliable degree of correctness somewhere. Think how miserable we would be if we were setting some text to blink on a webpage and when it doesn’t work… “Perhaps the CPU has an hardware bug”.
I know it’s an open source project, put together probably by very nice and positive people with the best intentions. It was just such an implausible and severe burn that I simply don’t dare to use the language anymore.
You’ve never found or heard of a bug in any other programming language or its standard library? And if you did, you would never use it? That would rule every production grade programming language, but OK.
Scala is quite a small language, it is just very expressive, making some people go overboard with fancy, “elegant” abstractions. That’s true for any expressive language, like lisps, ruby, etc. Don’t be those people.
I really don’t think it’s reasonable to claim these stuff about the language, especially with Scala 3 now being available that changed many of the pain points (you have to be more explicit around some of the easier to misuse stuff). It’s an elegant language that has a very strong type system, and was very early in combining the Functional and OOP patterns, taking the best from both.
I’ve heard more than a couple of stories of companies that picked it and then couldn’t keep up with hiring/complexity/etc. and eventually had to move off. That’s enough data points for me to not recommend it.
You can hear the exact same story about any niche language. Facebook Messenger and GitHub both moved off Erlang and rewrote their internals in C++. Bleacher Report famously rewrote their Rails stack in Elixir and achieved massive cost savings. Now they are being forced to rewrite in a mainstream language. Walmart is forcing a rewrite of their internal F# system (from the Jet.com acquisition).
By your logic we can never recommend picking any language outside of the mainstream. Which, sure, may be a valid strategy for some people. But let’s not pretend it’s about the specific technology.
Bleacher Report famously rewrote their Rails stack in Elixir and achieved massive cost savings. Now they are being forced to rewrite in a mainstream language.
By your logic we can never recommend picking any language outside of the mainstream
Yes, until the language becomes mainstream. Catch-22.
The examples above are mostly those where a large company needs to conform the software to their moulds for hiring, tooling, running etc. It’s probably better to recommend niche languages for smaller more limited operations (which is how the examples above started out).
Scala is the best language on the JVM for at least a decade and for the foreseeable future. Any big community can have blowups (see Rust’s moderators resignation fiasco, the RustConf fiasco) etc., and Scala users have quietly continued shipping while a few Extremely Online people spread FUD about it. Eg https://www.infoq.com/presentations/tesla-energy-platform/
Just a note that they rewrote in Rust, not eg Java. Rust makes sense for a service mesh when the competition is written in languages like C or C++. It’s a common pattern for an initial implementation to be written in a language that’s more familiar for a team and then rewritten to a more optimized version once they’ve learned the lessons of the domain. For example, Twitter was initially written in Ruby, which helped them to get off the ground and got them to the point where they were facing scalability issues, and then they rewrote in Scala.
I wouldn’t infer anything positive or negative about a language from project rewrites, which are driven by a variety of requirements beyond the purely technical aspect of the programming language.
I do attribute great negativity about the language from the rewrite. I believe Joel Spolsky is correct here: https://www.joelonsoftware.com/2000/04/06/things-you-should-never-do-part-i/ I conclude that the devs must have found Scala to be so bad that the only path forward they saw was to abandon in. Having tried to make small patches to linkerd 1’s scala code, I find the same thing: it is far too complex for something which should be simple.
This first version of Linkerd had a proxy component that was written in Scala, and leveraged the robust Scala and Java networking ecosystem for excellent performance at scale. But, because it ran on the Java Virtual Machine, it had a pretty significant resource footprint. (The JVM is good at “scaling up”, but not good at “scaling down”, as William wrote in his InfoQ article on the decision to reimplement Linkerd.) Even though the Linkerd community got pretty good at tuning the JVM’s memory use to minimize footprint, it was still too much to ask in a per-pod service mesh deployment model. So we knew we’d need a language that compiled to native binaries, like Rust, Go, and C++.
That post is three years old, and as far as I know most of the scala mainstream has excised Jon Pretty, Jon De Goes and others identified with toxic behavior.
I haven’t but I don’t see how it has a chance against C++ given the JVM, it just can’t fill all the roles that C++ can. Rust however does have that ability.
I haven’t but I don’t see how it has a chance against C++ given the JVM
There was a time, long ago before e.g. Java, when many applications were built in C++ that should not have been built in C++. The results were mostly horrible: late-to-deliver, over-priced, buggy, fragile, unmaintainable. C++ is a fine language for more advanced developers with a solid design and good management, but it has never been a good language for typical application developers.
Java (your example) did end up taking over most of the areas where C++ used to be used, but that is only because those applications should never have been targeting C++. For reference, I worked on or with a few of these C++ apps myself in the 1990s, and most of them died on their own before Java even appeared on the scene. One of them (in a relatively small company) ran up a bill of over a hundred million before finally dying, and back in the early 90s, that was a lot of money.
Yes. It seems like the language is too enterprise for some people, take a look here, on Lobsters, and you’ll find very few posts about Kotlin. But it’s a pleasure to work with. And in my case, it’s the language that pays the bills (and I’m not a mobile developer). Kotlin is the best imperative, object-oriented language right now in my opinion.
While Kotlin has several good features and syntactic sugar over Java, they really dropped the ball with pattern matching for some reason. Even Java’s far from fully developed pattern matching with switch/instanceof is significantly better and more capable, let alone Scala’s.
In the brief time I worked with Kotlin I found it very pleasant, and I can say for sure that it turned my friend who’s mostly only written Java into a fan of functional typed programming, so there’s definitely something to it.
I don’t see why anybody would write Java really. Kotlin/Spring/Boot is considered a great stack. The work Jetbrains is doing on Kotlin Multiplatform is also pretty nifty if it pans out.
Yay! Thanks Rust for introducing great ideas like static typing, exhaustive pattern matching, type inference, option types instead of null, and result types instead of exceptions! We would have never known about all this but for Rust.
Rust certainly made these features more mainstream. It’s made them very visible and I’m just really happy about it. FP languages didn’t really have the weight and influence for that.
It’s especially impressive because they bootstrapped the compiler from the start. Rust was always written in Rust. There was never another implementation language. Nope, don’t look into it. Just cite me as a source.
This is good. I do believe that any language without sum types and exhaustive pattern matching is a dead man walking in 2024. It’s such an obviously useful thing and weird OOP hacks like the visitor pattern just don’t cut it once you’ve seen how nice it is to have these features.
To some extent you don’t really need those as language features, though. I use the OneOf package for C#, and it’s Good Enough. Yeah, match is a method on OneOf objects, not a keyword, but that’s fine. It completely covers my main use-case, which is a non-nullable Result type, and a bunch of other use-cases that I don’t really use.
Python has been adding a lot of features in this direction as well, and I feel similarly - very much here for it. The cat example could look something like:
@dataclasses.dataclass(frozen=True)
class DeadCat:
...
@dataclasses.dataclass(frozen=True)
class AliveCat:
is_hungry: bool
Cat = AliveCat | DeadCat
match real_cat:
case DeadCat():
...
case AliveCat(is_hungry):
...
I’m not sure you can get MyPy to do exhaustiveness checking (yet?) of the match clause though?
Anyway: I often find myself missing ownership for the purpose of “disposing” of objects through the type system - in Rust you often do APIs like “and once you’ve done this thing to it you don’t get the object back”, eg. you closed the file/transaction/socket or whatever. try-with-resources/with-statements just ain’t the same, I want my compile error.
These features have been useful, because it’s allowed a lot of the creature comforts of building type safe services, while being in a language our quantitative analysts and data scientists read and understand. Got my fingers crossed that the Mojo language effort pans out, because it promises kind of another level of this.. maybe.
I have not used Python 3.11, but mypy is pretty good at doing exhaustiveness checks with if clauses so it would be kinda surprising if it did not with match.
One does need to sprinkle assert_never here and there but it does work :)
In previous $WORK we used the errorprone compiler plugin[1] from Google and turned a bunch of things around try-with-resources up to error, that had the same effect of turning a whole class of issues into build failures. Super nifty! There’s a great Gradle plugin for it as well.
It’s pretty pluggable, there are some good examples of adding new checks in [2]
I imagine Scala did have some unavoidable influence on Rust owing to its existence (Rust even used to use square brackets for type parameters at one point), but much stronger was the influence of Standard ML and OCaml that Rust shares with Scala. The Haskell influence became more prominent when Rust added traits for overloading and bounded polymorphism (while Scala has ‘traits’, Rust’s traits are much closer to type classes).
Now, a plain ol’ Java object (aka POJO) is often written with mutability by default, and rather verbosely. Here is how it looks like in Java 8
I don’t mean to be rude, but the author is really confused to a very basic point. A POJO is not written with mutability by default. That is silly. The author means a javabean. The purpose of javabeans was for GUI and other tooling being able to handle them automatically by relying on the getter and setter convention. Back in the day, there were plenty of libraries and IDE tools that used this convention. There is nothing particularly “plain old” about the javabean convention. The term POJO was used in enterprise javabeans to emphasize that EJBs 3 were just normal objects. Contrary to EJBs 2 which were not.
If you go around polluting all your objects with getters and setters because you think it’s how it’s done, do know that you are wasting your time and create a huge bulk of noise that serves no purpose at all.
If you go around polluting all your objects with getters and setters
It was fairly common and this StackOverflow response lists some reasons to do it. I take it you disagree, but I think it’s fair to say there is no consensus.
They list them as ‘advantages’. I think precisely because if they were reasons, most people would immediately say: but I don’t need any of those.
Indeed, the reason I mentioned, which was the motivation for this pattern to spring to life, is listed in there.
Of all those, there’s the one of providing a debug point for access and mutation of an attribute. That is the only one would could claim that cannot be planned ahead of time. Other justifications all feel like: when you specifically need it, do it then, not before.
I also think the fact that people conflate this with the definition of POJO decieves people into this sense of “this is how it has always been done”.
In a sense this is the opposite of a plain old object. It’s a specific kind of object with peculiar characteristics.
I like to think of the Java Bean convention as structural typing for the JVM. It allows libraries to interact with your “objects” without knowing anything about it on the type system level.
I thought it odd that they included getters and setters in the example, because that was really orthogonal to their point: fields in java objects are mutable by default.
That pattern and the term POJO may have originated from java beans, but they spread beyond that a long, long time ago. I was taught to write them (with some rationale) more than 20 years ago at undergrad level. I’ve still never written a javabean.
You are confused. The term did not originate from javabeans. It originates from Enterprise java beans. The concept of javabeans has been there since the beginning. There was no POJO because there were no EJBs, hence there were no two types of classes to dintinguish from each other.
All the classes you have ever written in java are POJOs, what you have never written is an Enterprise Java Bean.
I have no clue why people mix these up, but the confusion seems to be widespread.
I’ll readily accept that I’m mixing up javabeans and EJBs. I’ve written neither. The author mentioned neither, either: you introduced them in this thread, and they are irrelevant to the point the author is making.
I’ll readily accept that I’m mixing up javabeans and EJBs. I’ve written neither. The author mentioned neither
They did. They introduced javabeans. They just called them POJOs, which is an obsolete term that doesn’t mean anything anymore.
they are irrelevant to the point the author is making.
My point is precisely that the fact the object is a javabean is irrelevant. Mutability has nothing to do with using acessor methods versus just referencing an atribute directly, as the author claims.
It seems that the most common use of an “object” in Java these days, is to just be a data container. Other code (often called a controller, service or manager) acts on or queries that data. A “record” just formalizes that?
I would disagree that it is the most common use. Fundamentally, certain objects are there only to store data, and be “a record”, like JPA entities, DTOs, etc, but many other kind of object is absolutely not like that, e.g. an HTTPConnection is not the same as another, even if all their fields were the same.
I think thinking of it as identity-having objects vs value-classes can be useful.
Yes, I should have qualified that the data container objects I’m talking about are really in the problem domain, not the plumbing, framework or application related.
Do you ever see an object-oriented domain model, as opposed to “services” and “managers” in applications driven by things like Spring/Boot these days?
As the author says, these features also come from Kotlin and Scala, and they are immutable objects, abstract data types (via sealed interfaces and exhaustive switches), and require Java 21 with some experimental flags.
It kinda feels like Rust getting credit for ideas it took from other languages is a really common pattern.
It’s rather unfortunate, as Graydon and others from Mozilla Research were extremely open about Rust’s influences from the very beginning, and that really opened my eyes to the wider world of programming language design. You can see part of this living on the current bibliography, but sadly it’s a bit hard to find. As the development team and the community has scaled it seems like it’s been harder and hard to keep this knowledge alive and well-known, and I think this is a real problem.
At the very least, I do really like how the RFCs reference prior art… it’s incredibly frustrating when languages like C++ fail to include this information in their standard proposals.
For an interesting discussion between Greg Morrisett (one of the creators of Cyclone) and Felix Klock (who was an early contributor to Rust), I highly recommend the fireside chat from last year’s ICFP.
As a follow up, I should note that discourse around Rust is far from the only place where this happens, it’s just is very prominent at the moment. Our entire industry needs to be better at teaching new and existing programmers about context and history… even if that requires working against structural pressures that encourage us to portray every exciting technology as springing out of nowhere.
I would have really liked my computer science course to have taught me more about the history of the programming languages and technologies we use. Unfortunately, computing history seems to be very unpopular with my fellow students. I suspect it’s because it’s not immediately applicable to a career. I think that, at least where I’m from, most students of computer science are after a fast track to a lucrative job.
Edited to add: perhaps that’s too harsh on my fellow students; but I do think that most people are primarily interested in what they can do now (because that’s the most immediately practically relevant) and not what has come before.
Yeah, definitely agree. I think this is something that would be great as a first semester class, to provide context for the rest of the course. It’s one of those things that can be painful a at the time, but you look back on with fondness and can really change your perspective on the world (I had a similar art and design history class as part of a graphic design degree).
I think it would be possible to do this as part of introductory programming.
That is start out with simple programs in some sort of Basic as someone starting out hobby programming in the 80s, and work yourself forward in time adding concepts as you go.
Maybe not worth building the whole curriculum around, but could work as a first semester intro to programming schedule.
[Comment removed by author]
Kotlin is criminally underrated IMO. So much more more expressive and pleasant to write than Java with the same enormous ecosystem.
Kotlin is honestly my favorite language, at least in a practical context (you’ll pry Smalltalk and Common Lisp from my cold, dead, zombie hands). But the fact it comes from JetBrains, who adamantly refuse to implement an LSP, means that using it at high levels of effectiveness basically requires using JetBrains’ IDEs. I don’t mind needing Fleet or IntelliJ when I actually need to go all-in, but lacking a reasonable way to quickly slap together a Kotlin script with autocomplete and whatnot from Helix or Emacs or whatever does grate after awhile in a way that e.g. F# on .NET Core does not.
Yes, there are a couple of third-party LSPs for Kotlin, but neither of them have been good enough to let me do basic Android development in Emacs. And given how badly Android Studio runs on the hardware I actually own, that strongly discourages me from developing for Android.
Have you played with scala? Like rust it’s substantially an attempt to smash c++ and ML language families together
Many years ago I wrote a web crawler in scala. The actor library in the standard Library allowed me to write a single script and execute it with the need for dependencies. It loved the fact that it had a clean and compact syntax. And with the actor model ready to use of box, it was easy to implement concurrency models.
The crawler would run well, but after an hour or so, it would reach a deadlock state. I couldn’t figure out what I was doing wrong. I searched everywhere, went to the community to ask for help but in the end I gave up as I found no solution. Some 5 years or so after, inred online that the actors library from the stdlib was going to be retired and among the reasons, there was a bug which was exactly the problem I had.
Never again. I have used 20+ programming languages professionally for decades and never once I have stumbled upon a bug on the programming language that directly breaks the main functionality like this. Even in new experimental languages. I simply lost the trust that it works. No way I am touching it again.
I also think they suffer for the same problem as Perl. Too many ways to do simple things, to the point that the language becomes cryptic.
Can you link to the bug, for my reference?
It was MANY years ago. I don’t even have the source of that project anymore. The crawler, I wrote it 12 years ago. If you look into the retirement of the Actor library announcement you might be able to navigate to it. I believe that was perhaps 5-7 years ago or so.
I cannot find any mention of this specific bug in the
scala.actorsmigration guide: https://web.archive.org/web/20220927111015/https://docs.scala-lang.org/overviews/core/actors-migration-guide.htmlUnfortunately, we’ll just have to take your word for it that Scala is full of bugs that ‘break the main functionality’ (despite your admission that the buggy library itself was removed) ;-)
I didn’t said it was full of bugs. I mentioned one bug. I have never encountered another but in a programming language. When I am writing code, and something doesn’t work, I never ever for a second assume that it could be an error in the programming language. I think that that sacred frontier is important. We have to be able to assume a reliable degree of correctness somewhere. Think how miserable we would be if we were setting some text to blink on a webpage and when it doesn’t work… “Perhaps the CPU has an hardware bug”.
I know it’s an open source project, put together probably by very nice and positive people with the best intentions. It was just such an implausible and severe burn that I simply don’t dare to use the language anymore.
You’ve never found or heard of a bug in any other programming language or its standard library? And if you did, you would never use it? That would rule every production grade programming language, but OK.
Scala is considered mostly an anti-pattern of complexity and massively toxic at this point. Hard to recommend it to anybody.
Considered by who?
Scala is quite a small language, it is just very expressive, making some people go overboard with fancy, “elegant” abstractions. That’s true for any expressive language, like lisps, ruby, etc. Don’t be those people.
I really don’t think it’s reasonable to claim these stuff about the language, especially with Scala 3 now being available that changed many of the pain points (you have to be more explicit around some of the easier to misuse stuff). It’s an elegant language that has a very strong type system, and was very early in combining the Functional and OOP patterns, taking the best from both.
I’ve heard more than a couple of stories of companies that picked it and then couldn’t keep up with hiring/complexity/etc. and eventually had to move off. That’s enough data points for me to not recommend it.
You can hear the exact same story about any niche language. Facebook Messenger and GitHub both moved off Erlang and rewrote their internals in C++. Bleacher Report famously rewrote their Rails stack in Elixir and achieved massive cost savings. Now they are being forced to rewrite in a mainstream language. Walmart is forcing a rewrite of their internal F# system (from the Jet.com acquisition).
By your logic we can never recommend picking any language outside of the mainstream. Which, sure, may be a valid strategy for some people. But let’s not pretend it’s about the specific technology.
I had to look this up, so here’s more details on that: https://old.reddit.com/r/erlang/comments/18f3kl3/bleacher_report_gutting_out_otp/kcts58i/
Yes, until the language becomes mainstream. Catch-22.
The examples above are mostly those where a large company needs to conform the software to their moulds for hiring, tooling, running etc. It’s probably better to recommend niche languages for smaller more limited operations (which is how the examples above started out).
Which is exactly why I said:
Scala is the best language on the JVM for at least a decade and for the foreseeable future. Any big community can have blowups (see Rust’s moderators resignation fiasco, the RustConf fiasco) etc., and Scala users have quietly continued shipping while a few Extremely Online people spread FUD about it. Eg https://www.infoq.com/presentations/tesla-energy-platform/
That’s… sad. Have any sources for this?
I’ve also heard this first hand from people (complexity, hard to maintain etc) who had to then transition off of scala with big projects.
linkerd abandoned their 1.0 scala codebase and did a full write for 2.0
Just a note that they rewrote in Rust, not eg Java. Rust makes sense for a service mesh when the competition is written in languages like C or C++. It’s a common pattern for an initial implementation to be written in a language that’s more familiar for a team and then rewritten to a more optimized version once they’ve learned the lessons of the domain. For example, Twitter was initially written in Ruby, which helped them to get off the ground and got them to the point where they were facing scalability issues, and then they rewrote in Scala.
I wouldn’t infer anything positive or negative about a language from project rewrites, which are driven by a variety of requirements beyond the purely technical aspect of the programming language.
I thought that they rewrite in Go and not Rust. Upon checking, I see that it is both Go and Rust: https://github.com/linkerd/linkerd2
I do attribute great negativity about the language from the rewrite. I believe Joel Spolsky is correct here: https://www.joelonsoftware.com/2000/04/06/things-you-should-never-do-part-i/ I conclude that the devs must have found Scala to be so bad that the only path forward they saw was to abandon in. Having tried to make small patches to linkerd 1’s scala code, I find the same thing: it is far too complex for something which should be simple.
Why don’t we ask the devs themselves instead of assuming: https://linkerd.io/2020/07/23/under-the-hood-of-linkerds-state-of-the-art-rust-proxy-linkerd2-proxy/
Thank you for this.
This sort of thing might be what gp is talking about regarding toxicity: https://medium.com/@yifanxing/my-experience-with-sexual-harassment-in-the-scala-community-9245b4a139de
That post is three years old, and as far as I know most of the scala mainstream has excised Jon Pretty, Jon De Goes and others identified with toxic behavior.
Also lots of drama, bigotry etc. etc.
I haven’t but I don’t see how it has a chance against C++ given the JVM, it just can’t fill all the roles that C++ can. Rust however does have that ability.
There’s also scala native ;) but I think it competes more in the “better Java” space than in the systems programming language space.
There was a time, long ago before e.g. Java, when many applications were built in C++ that should not have been built in C++. The results were mostly horrible: late-to-deliver, over-priced, buggy, fragile, unmaintainable. C++ is a fine language for more advanced developers with a solid design and good management, but it has never been a good language for typical application developers.
Java (your example) did end up taking over most of the areas where C++ used to be used, but that is only because those applications should never have been targeting C++. For reference, I worked on or with a few of these C++ apps myself in the 1990s, and most of them died on their own before Java even appeared on the scene. One of them (in a relatively small company) ran up a bill of over a hundred million before finally dying, and back in the early 90s, that was a lot of money.
Yes. It seems like the language is too enterprise for some people, take a look here, on Lobsters, and you’ll find very few posts about Kotlin. But it’s a pleasure to work with. And in my case, it’s the language that pays the bills (and I’m not a mobile developer). Kotlin is the best imperative, object-oriented language right now in my opinion.
While Kotlin has several good features and syntactic sugar over Java, they really dropped the ball with pattern matching for some reason. Even Java’s far from fully developed pattern matching with switch/instanceof is significantly better and more capable, let alone Scala’s.
In the brief time I worked with Kotlin I found it very pleasant, and I can say for sure that it turned my friend who’s mostly only written Java into a fan of functional typed programming, so there’s definitely something to it.
I don’t see why anybody would write Java really. Kotlin/Spring/Boot is considered a great stack. The work Jetbrains is doing on Kotlin Multiplatform is also pretty nifty if it pans out.
Java has always supported Abstract Data Types since its release in 1995
I think they meant the other ADT: algebraic data types. Those are more recent in Java if I understand correctly.
Your no doubt correct. However, I feel that incorrect information should not go without comment.
Sorry that should have read algebraic data types.
Yay! Thanks Rust for introducing great ideas like static typing, exhaustive pattern matching, type inference, option types instead of null, and result types instead of exceptions! We would have never known about all this but for Rust.
Rust certainly made these features more mainstream. It’s made them very visible and I’m just really happy about it. FP languages didn’t really have the weight and influence for that.
In my experience these features are and were well-known, but nobody wanted to learn Haskell to utilise them.
It’s especially impressive because they bootstrapped the compiler from the start. Rust was always written in Rust. There was never another implementation language. Nope, don’t look into it. Just cite me as a source.
This is good. I do believe that any language without sum types and exhaustive pattern matching is a dead man walking in 2024. It’s such an obviously useful thing and weird OOP hacks like the visitor pattern just don’t cut it once you’ve seen how nice it is to have these features.
To some extent you don’t really need those as language features, though. I use the OneOf package for C#, and it’s Good Enough. Yeah, match is a method on OneOf objects, not a keyword, but that’s fine. It completely covers my main use-case, which is a non-nullable Result type, and a bunch of other use-cases that I don’t really use.
Python has been adding a lot of features in this direction as well, and I feel similarly - very much here for it. The cat example could look something like:
I’m not sure you can get MyPy to do exhaustiveness checking (yet?) of the match clause though?
Anyway: I often find myself missing ownership for the purpose of “disposing” of objects through the type system - in Rust you often do APIs like “and once you’ve done this thing to it you don’t get the object back”, eg. you closed the file/transaction/socket or whatever. try-with-resources/with-statements just ain’t the same, I want my compile error.
These features have been useful, because it’s allowed a lot of the creature comforts of building type safe services, while being in a language our quantitative analysts and data scientists read and understand. Got my fingers crossed that the Mojo language effort pans out, because it promises kind of another level of this.. maybe.
I have not used Python 3.11, but mypy is pretty good at doing exhaustiveness checks with if clauses so it would be kinda surprising if it did not with match. One does need to sprinkle
assert_neverhere and there but it does work :)In previous $WORK we used the errorprone compiler plugin[1] from Google and turned a bunch of things around try-with-resources up to error, that had the same effect of turning a whole class of issues into build failures. Super nifty! There’s a great Gradle plugin for it as well.
It’s pretty pluggable, there are some good examples of adding new checks in [2]
[1] https://errorprone.info/
[2] https://github.com/palantir/gradle-baseline/
More like, Java is becoming more like Scala, which heavily influenced rust and was heavily influenced by Haskell.
I imagine Scala did have some unavoidable influence on Rust owing to its existence (Rust even used to use square brackets for type parameters at one point), but much stronger was the influence of Standard ML and OCaml that Rust shares with Scala. The Haskell influence became more prominent when Rust added traits for overloading and bounded polymorphism (while Scala has ‘traits’, Rust’s traits are much closer to type classes).
Fair point, ML influenced both as well.
I don’t mean to be rude, but the author is really confused to a very basic point. A POJO is not written with mutability by default. That is silly. The author means a javabean. The purpose of javabeans was for GUI and other tooling being able to handle them automatically by relying on the getter and setter convention. Back in the day, there were plenty of libraries and IDE tools that used this convention. There is nothing particularly “plain old” about the javabean convention. The term POJO was used in enterprise javabeans to emphasize that EJBs 3 were just normal objects. Contrary to EJBs 2 which were not.
If you go around polluting all your objects with getters and setters because you think it’s how it’s done, do know that you are wasting your time and create a huge bulk of noise that serves no purpose at all.
It was fairly common and this StackOverflow response lists some reasons to do it. I take it you disagree, but I think it’s fair to say there is no consensus.
They list them as ‘advantages’. I think precisely because if they were reasons, most people would immediately say: but I don’t need any of those. Indeed, the reason I mentioned, which was the motivation for this pattern to spring to life, is listed in there.
Of all those, there’s the one of providing a debug point for access and mutation of an attribute. That is the only one would could claim that cannot be planned ahead of time. Other justifications all feel like: when you specifically need it, do it then, not before.
I also think the fact that people conflate this with the definition of POJO decieves people into this sense of “this is how it has always been done”. In a sense this is the opposite of a plain old object. It’s a specific kind of object with peculiar characteristics.
Go to most Java codebases and it is still the way.
I like to think of the Java Bean convention as structural typing for the JVM. It allows libraries to interact with your “objects” without knowing anything about it on the type system level.
I thought it odd that they included getters and setters in the example, because that was really orthogonal to their point: fields in java objects are mutable by default.
That pattern and the term POJO may have originated from java beans, but they spread beyond that a long, long time ago. I was taught to write them (with some rationale) more than 20 years ago at undergrad level. I’ve still never written a javabean.
You are confused. The term did not originate from javabeans. It originates from Enterprise java beans. The concept of javabeans has been there since the beginning. There was no POJO because there were no EJBs, hence there were no two types of classes to dintinguish from each other.
All the classes you have ever written in java are POJOs, what you have never written is an Enterprise Java Bean.
I have no clue why people mix these up, but the confusion seems to be widespread.
https://en.wikipedia.org/wiki/JavaBeans
I’ll readily accept that I’m mixing up javabeans and EJBs. I’ve written neither. The author mentioned neither, either: you introduced them in this thread, and they are irrelevant to the point the author is making.
They did. They introduced javabeans. They just called them POJOs, which is an obsolete term that doesn’t mean anything anymore.
My point is precisely that the fact the object is a javabean is irrelevant. Mutability has nothing to do with using acessor methods versus just referencing an atribute directly, as the author claims.
Which JEPs are used in this blog post? Why do they need previews enabled? Sealed classes were added in release 17.
Is it because of JEP 441: Pattern matching for ‘switch’ or 440 Record patterns? But none are them previews…
It is for using
_in the switch at :This is JEP 456 - Unnamed Variables & Patterns which is in preview for Java 21 and became final in Java 22
It seems that the most common use of an “object” in Java these days, is to just be a data container. Other code (often called a controller, service or manager) acts on or queries that data. A “record” just formalizes that?
I would disagree that it is the most common use. Fundamentally, certain objects are there only to store data, and be “a record”, like JPA entities, DTOs, etc, but many other kind of object is absolutely not like that, e.g. an HTTPConnection is not the same as another, even if all their fields were the same.
I think thinking of it as identity-having objects vs value-classes can be useful.
Yes, I should have qualified that the data container objects I’m talking about are really in the problem domain, not the plumbing, framework or application related.
Do you ever see an object-oriented domain model, as opposed to “services” and “managers” in applications driven by things like Spring/Boot these days?