Scala 3 Migration: Report from the field

(blog.pierre-ricadat.com)

159 points | by AzzieElbab 92 days ago

17 comments

  • caterama 92 days ago
    Scala used to be my hobby / enthusiast language. Introduced to it through a college course, and used a bit through school. Later, I would use it for Advent of Code, tinkered with a Scala Play webapp, and dream about using it professionally. Rust has almost completely filled that void now. Rust is native, I'm not waiting on the 1.0 release of `scala-native` anymore. The community around Rust seems to be enthusiastic and growing, as opposed to languishing for Scala. I hold some reservations about Rust in terms of how complicated it is. Despite having used it for an amount of time that I would be feeling comfortable in most languages, I am still not comfortable and continually encounter _stuff I don't understand_.

    RIP Scala, I will miss you! You showed me the joy of pattern matching, functional OO, currying, how to use `map` `flatMap` `fold`, etc. All things with continued influence! <3

    • joshlemer 92 days ago
      > Scala Play webapp

      I feel like the biggest misstep that the Scala ecosystem and Typesafe/Lightbend did was that they didn't invest more in Play Framework. 10 or 12 years ago, Play had a lot of energy and momentum, and it's a kind of thing that has broad enterprise/start up appeal. But focus was always more on Akka and what seemed like really niche architecture astronaut stuff like Actors and Actor System Clusters and Event Sourcing etc, rather than getting the basics to be super ergonomic or productive.

      If they had keep just making Play Framework better and better and focusing on the practical problems that every web service faces, they could be in a similar great position as Laravel is in today or any of the many Rails/Laravel consultancies.

      • lmm 92 days ago
        > I feel like the biggest misstep that the Scala ecosystem and Typesafe/Lightbend did was that they didn't invest more in Play Framework. 10 or 12 years ago, Play had a lot of energy and momentum, and it's a kind of thing that has broad enterprise/start up appeal. But focus was always more on Akka and what seemed like really niche architecture astronaut stuff like Actors and Actor System Clusters and Event Sourcing etc, rather than getting the basics to be super ergonomic or productive.

        I'd say the opposite. They pushed Play a lot. But it was never a killer app, and it never even really leveraged the strengths of Scala.

        People and especially companies don't switch languages for "super ergonomic and productive". They switch because they want to do something they can't do in their current language. I'm not a fan of Akka or Actors, but it made for some incredible demos that you really couldn't do in anything else except Erlang.

        • joshlemer 92 days ago
          I disagree, productivity and ergonomics drives plenty of popular tools - React, Laravel, Rails, React Native, etc.
          • lmm 91 days ago
            Hmm. Fair point for Rails and Laravel (whereas I think React had a killer app in terms of being able to make SPAs without going crazy) but those are tools that you can pick up for a one-off throwaway project - indeed I suspect most adopters didn't "move" to them so much as start doing projects in them and eventually stop doing projects in other things. Scala was never really competing in that space - I don't think anyone would ever say "let's make our website for the next tradeshow in Play" - it's a "heavy" language that needs an IDE and deep familiarity to get the best out of it (and partly that's also what JVM folks would be expecting). So it needed to play for the big core codebases, and for a while it did (particularly when there was no alternative to Spark).

            Could they have made Play an alternative to Rails for one-off throwaway websites? Maybe, but the thing that would have needed to be different wouldn't be pushing Play itself, but rather lighter tooling and making it easier to get from zero to pages being served. Honestly I struggle to see how they could've done it without making the compiler and build tool much faster, and either making the IDEs much more efficient (difficult) or making the language easier without an IDE (difficult, and would risk splitting efforts). And even then, you wouldn't really show the compelling advantage of Scala, which is fearless refactoring in large codebases. I don't know that it could ever have been better than Rails at what Rails does, and also we already have Rails. Whereas even if it eventually "dies", Scala has already pushed Java and Kotlin to be much better than they were.

            • joshlemer 91 days ago
              I mean, I don't find that working with IntelliJ makes it any "heavier" than other languages in terms of prototyping. I use PHP Storm for Laravel development and I never say to my self, "if only I wasn't using an IDE, maybe I could get this site put together faster". Quite the opposite, Intellij makes me super productive.

              I think all of these frameworks - Laravel, Rails, Django, Next.js, Spring - require deep familiarity to get the best out of them.

              > Honestly I struggle to see how they could've done it without making the compiler and build tool much faster

              Well, Lightbend literally was the owner of Play, SBT, and Scalac. They were in a perfect position to make the build tool and compiler much faster. Or even if SBT can't be made much faster, ditch it and make integration with gradle and/or maven really great.

              • lmm 91 days ago
                > I use PHP Storm for Laravel development and I never say to my self, "if only I wasn't using an IDE, maybe I could get this site put together faster". Quite the opposite, Intellij makes me super productive.

                But the first time you tried out PHP, did you have to install the IDE first? Did you have to change your existing PHP tooling setup the first time you tried out Lavarel?

                I would agree that IDEs are an improvement over not using them in most languages, but my feeling the "tooling curve" is much steeper for Scala than for something like PHP.

          • acjohnson55 91 days ago
            Yeah, but I don't think Play (which I enjoyed) was ever going to top those, unless it had a fundamentally new idea to bring.
            • joshlemer 91 days ago
              Laravel and Django didn't bring fundamentally new ideas above and beyond Rails.
        • hocuspocus 92 days ago
          That is correct.

          Play's hype did more harm than good. I work at a company that has many legacy projects in Scala because we were/are heavily invested in Spark, and Play is a disaster overall.

          • joshlemer 91 days ago
            What is so bad specifically about play?
            • hocuspocus 91 days ago
              Like KajMagnus mentioned:

              - The churn caused by breaking changes in minor versions used to be annoyingly high.

              - Slick looks neat at first but caused a lot of friction when used by less experienced developers.

              - The fact Akka is in your dependency tree encourages people to reach for it and raw actors are usually a bad choice. Akka streams work well for websockets and SSE but it's another footgun.

              Additionally:

              - It was in state of semi-abandonment for several years before Lightbend gave the project to the community. Even though there are/were big companies deploying Play apps at scale, for instance Apple.

              - The introduction of Guice (in 2.4 afaik) was a terrible mistake, completely unnecessary and at odds with the Scala philosophy. Sure you can not use it, or use something else (like macwire) but defaults matter.

              - Play-JSON depends on Jackson which is annoying in the JVM world, causing binary compatibility issues when you have diamond dependencies.

              - Standard library Futures are not so nice when you've experienced anything else (Scalaz Task, Cats IO, ZIO, even Twitter Future...)

              - Code generation from routes files is an odd choice when Scala has always been expressive and DSL friendly.

              - Swagger/OpenAPI integration is brittle.

              I've personally used Tapir since 2019 and couldn't be happier. All Play apps still running at my company are being abandoned or replaced by Spring/Java projects.

              • KajMagnus 91 days ago
                Tapir looks nice, didn't know about. Can I ask, do you use it together with Netty? How fast is it for you? (if you happen to have benchmarked it)

                Have you tried Vertx with Scala? (Or Spring + Scala, or sth else?)

                > The introduction of Guice

                Personally I've wired everything statically at compile time, zero dependency injections. (Felt as if what I did went a tiny bit against the framework, but works fine.)

                • hocuspocus 91 days ago
                  I use Tapir with http4s as the http server isn't my bottleneck anyway and I like Cats Effect and fs2.

                  But SoftwareMill has done extensive benchmarking to make sure the overhead from Tapir vs calling the http backend directly was insignifiant. I believe Netty is the recommended backend if you want direct style (i.e no effect systems) on Java 21+ virtual threads even though Oracle's Helidon Níma is supported too.

                  • KajMagnus 91 days ago
                    Thanks! Ok, seems direct style is what I would want, after having asked an LLM: it says it's then simpler to debug async call stacks, with Java 21+ virtual threads.

                    Nice to know that there are good alternatives, if time it is some day to migrate away from Play.

              • joshlemer 91 days ago
                > Slick

                Totally agreed, Slick is definitely not a good way to access the database. It massively over complicates things and was a massive oil spill that destroyed the maintainability of many codebases. But that's not really Play, specifically, just a library that lots of people used with Play. I personally was always more a fan of https://scalikejdbc.org/, if not just plain JDBC

                > It was in state of semi-abandonment for several years

                Yes, this is my main complaint. I remember on the front page for like 5 years after TypeSafe Activator had been totally removed from the internet, the Play website was still showing Activator commands. To this day, the Play site still hasn't removed their line about how they support CoffeeScript and Less.

                > Guice (in 2.4 afaik) was a terrible mistake, completely unnecessary and at odds with the Scala philosophy > Play-JSON depends on Jackson > Standard library Futures are not so nice

                Well, it turned out that the Scala Philosophy wasn't the be-all and end-all anyways, and was always changing (at some point DSL's were in, then they were out. The way people encode TypeClasses changed over the years, selectDynamic/applyDynamic were in and then they were out, symbols were everywhere and then deprecated, implicit conversions were in and then "best practice" switched to Converters) and there was always at least 2 camps who had very different philosophies. Guice is probably the most popular DI tool in the JVM world so seems to make sense to use it.

                The Jackson dependency and Scala Future's shortcomings might be annoying to many, but I don't think they really hindered adoption. Even in your case, what happened? At your company they're ripping out Play and replacing it with Spring, which uses DI very similar to Guice, probably depending on Jackson, and using java Futures (if they're doing async at all).

                • hocuspocus 90 days ago
                  It's true some Scala features or patterns fell out of fashion but I don't recall any time where replacing compile-time logic with annotation based runtime reflection was considered a good idea. And I don't think Guice was ever the most popular JSR-330 implementation, at least not when Play started using it. Spring had been dominating the Java world for several years by then. Funnily enough in the Android world I remember Dagger being very popular exactly around that time as people figured compile-time automatic DI is a lot saner than Guice.

                  Of course Spring is another can of worms entirely and I find many aspects infuriating. But things like diamond dependencies are less of an issue thanks to Maven BOMs which are common in the ecosystem.

                  My point is that ~10 years ago people started using Spark at my company, got curious about Scala and thought Play was compelling. Nowadays Spark (in Scala) is less ubiquitous and these teams remember that so many people got burned by Play before.

                  Funnily enough the peak of Scala's hype which I believe plateaued between 2014 and 2019 before dropping sharply was mainly driven by:

                  Spark: ground breaking in many ways but has become a huge liability to the ecosystem, holding so many libraries back. Databricks is also the main financial contributor to the Scala Center (I believe) while not giving much of a damn about the community or Scala 3 altogether. Spark is a very frustrating piece of software overall and today 95% of users are in PySpark anyway, avoiding JVM dependency hell being one reason.

                  Play: good idea, questionable execution, poor governance, and today mostly irrelevant to the future of Scala. Props to community maintainers who managed to secure funding and brought the framework back from the dead, saving many projects from a certain death.

                  Akka: also ground breaking, pretty much the only game in town if you need stateful cluster sharding, deployed at scale by top-tier companies. But also overkill for most people, and on top of that the relicensing really hurt the community and broke trust.

                  The boons and banes of Scala.

            • KajMagnus 91 days ago
              I use Play, and I think it is a good web framework, nowadays.

              In the past, however, upgrading to new versions, was annoying, because of pretty big changes in the API. (Don't know if this is what GP had in mind though.)

              And even worse (I suppose) for people who were using the different ORMs which have come and gone, instead of plain SQL.

              Akka has been annoying too: Adding WebSocket to my project, using Akka, was extremely much more complicated than doing the same in Nodejs (at least looking at the Nodejs docs I've seen).

              Today, to me, Play is feature complete and all I want is maintenance updates (and performance optimizations but not so important). And yes, that's how things look right now: Some bigger companies pay an open-source maintainer, so Play gets regular maintenance updates, but not any annoying major API changes (or so I hope), nice.

              Play has become boring in a good way? :- ) (Thinking about some "Use boring tech" HN posts.)

      • rco8786 92 days ago
        Totally agree. I wrote a few Play apps way back when and really enjoyed it. I was so excited about the future of the framework and how it would beat out Java for web apps, and steal folks away from the Rails ecosystem.

        And then it just…stopped. Not sure what happened there honestly.

    • threeseed 92 days ago
      I have been writing Scala and Rust everyday for the last few years.

      I actually don’t see the two overlapping all that much. Rust is a terrible backend language compared to Scala/JVM. When you are dealing with real world concurrency i.e. error/thread management Rust’s memory management model becomes unusably complex very quickly. And the entire ecosystem lacks maturity i.e. the majority of libraries I use are not at version 1.

      Whereas from Scala you can just use any Java library e.g. Vertx, Spring almost all of which have commercial, enterprise support and continue to be proven time and time again. It almost always just works.

      Rust’s strength is in desktop apps e.g. Tauri and low-level programming.

      • packetlost 92 days ago
        > When you are dealing with real world concurrency i.e. error/thread management Rust’s memory management model becomes unusably complex very quickly

        I've seen this several times, but having built several highly concurrent applications in Rust, I just don't agree. Building a concurrent Rust application the wrong way is certainly complex, but if you know how Rust's strong opinions on how to structure an application work, it's downright pleasant.

        Except async. Rust's async story still sucks and should be avoided as much as possible.

        • threeseed 91 days ago
          Compare this to Scala and it just doesn't matter about right/wrong way.

          It all just works without issue. Maybe you use a few more CPU cycles garbage collecting but these days it's unnoticeable.

          • packetlost 91 days ago
            I'm not speaking bad of Scala or the JVM: I actually agree. When the GC and overhead don't matter, a JVM language is an absolutely fantastic choice. I was more commenting that Rust can be simple if you architect it right, that's all.

            I've mostly come to the conclusion that a mediocre engineer can write performant enough Java/Scala/Clojure/Kotlin/etc. Usually even more performant than what an inexperienced/mediocre C/C++/Rust engineer could write and have an easier time doing it. However trying to ilk out the last bit of performance in a JVM language can be very challenging.

      • estebank 92 days ago
        > And the entire ecosystem lacks maturity i.e. the majority of libraries I use are not at version 1.

        I'm marginally bothered by the reluctance to bite the bullet and accept a 2.0 will happen in the future, but version numbers do not make for mature libraries. There are plenty of foundational libraries written in C keeping Linux desktops running that are permanent 0.x versions.

        > Whereas from Scala you can just use any Java library e.g. Vertx, Spring almost all of which have commercial, enterprise support and continue to be proven time and time again.

        I find that "wide and storied library ecosystem" can be a double edged sword: an old library can either be battle-tested, or just old (with cruft or poor design or implementation) and you can't always tell which it is ahead of time. This is true for libraries in any language, and the same thing will happen to Rust in 10 years.

        • threeseed 91 days ago
          > but version numbers do not make for mature libraries

          No but they do symbolise a belief amongst the library maintainers that it isn't stable. And so I end up spending an inordinate amount of time refactoring for the latest version.

          > and the same thing will happen to Rust in 10 years

          From what I've seen in the last year it won't. Most of the libraries I use have stopped being maintained. The reason Java does so well here is because in enterprise space supporting something for decades is common.

      • Sunscratch 91 days ago
        I double that. Rust is great language, and I like it a lot. But usually I pick Scala whenever I can, it’s perfectly suited for complex domain.

        So my rule of thumb is: Large enterprise monolithic projects - Scala. Microservises, serverless functions, systems where resources have hard constraints, cli apps - Rust.

        Both are great languages.

    • drdude 92 days ago
      I thought I was reading my own story! same here... 10 years of Scala 2.xx till it was Scala 3 that caused my withdrawal, and that infinite waiting for scala-native... killed my interest. Now, and for the foreseeable future, it is Rust.

      I had a look at Mojo, love it, but I am no longer interested in OO (used OO for 20+ years and I figured I am no more interested).

      EDIT: even John DeGoes (the ZIO guy) left Scala for similar reasons, now I just remembered, and prefers Rust over it... I love what they are doing with their Golem Cloud.

      • Sunscratch 91 days ago
        I would argue that John left due to political reasons mostly, and honestly, for good.
        • drdude 91 days ago
          True, but his article (https://degoes.net/articles/splendid-scala-journey) states it is also for Scala new syntax breaking a lot of things (if I remember correctly, been a a while since I read it) and for other reasons. I also thought it was for political reasons before until I read that article back in time.
      • AzzieElbab 91 days ago
        Jon DeGoes still works on the ZIO ecosystem along with his Rust projects.
    • markus_zhang 92 days ago
      I work in data engineering and Scala fades even in this field.
      • flakiness 92 days ago
        What's used instead? Python? (complete outsider, just curious.)
        • markus_zhang 92 days ago
          Python mostly, and Java if you are using Flink. We do both. The thing with Scala is, it's mostly linked to Spark, and then probably a good portion of the gigs out there using Spark are using Databricks, and Databricks is pretty expensive, so people are moving away from it. At least this has been my case for two companies -- one moved to self-host Vertica and the other is about to move to Flink.
        • joshlemer 92 days ago
          Yes. Java, Python.
          • flakiness 92 days ago
            Ok so boring things won. (Well I'm writing Java and Python every day outside Data context this is not dissing.)
            • markus_zhang 92 days ago
              Just curious what do you do? I'm thinking about moving away from data, maybe into something that is a little bit lower-level.
              • flakiness 91 days ago
                Java (+Kotlin) for Android, Python for its automation and tooling (and obviously, data.) These aren't very low-level - For Android there is always C++ if you want to go down to metal.
                • markus_zhang 91 days ago
                  Ah that's interesting. And there is ofc Swift and ObjC for Apple devices. Maybe I should get into app dev.

                  Thanks. Do you think there is a strong market of Android/iOS native app development? As a DE I don't think my previous experience worths much -- maybe a bit more when we move to Flink which uses Java, and the might would rather hire new graduates instead of me.

                  • flakiness 90 days ago
                    I don't expect native mobile dev market to grow and was wondering how other disciplines like data is doing ;-)
                    • markus_zhang 89 days ago
                      Data is still a big thing, but nowadays vendors successfully removed most of the management because people just want to get things done, so a lot of companies are moving to Snowflake and similar places. You basically do some click ops and hopefully shit sticks on the walls.

                      Interesting if you just like data, but bad if you like the tech beneath. I'd recommend moving away from DWH part of data engineering if you can, and focus on OLTP, streaming which are more technical. The culture is also different.

    • hackingonempty 92 days ago
      It depends on what you want to do, of course, but for back end servers the Rust ecosystem is relatively immature. There is nothing comparable to ZIO in Rust world, for example.
      • margorczynski 92 days ago
        What's more important than the current state is the direction where it's heading. Rust has energy, vision and momentum - additionally it has a powerful niche that it dominates.

        Scala has unfortunately fizzled out, I would say mainly because of incompetent leadership (or more precisely academia-driven) but also because the alternatives got much better since it got introduced (Java mainly). Which is a shame as it is a great language that offers elegance and great power.

  • dtech 92 days ago
    I left the Scala ecosystems (mostly) a year or 4 ago, right around the release of Scala 3. It's a shame that the compatibility and tooling situation doesn't seem to have improved much since then. The Scala devs always said they wanted to avoid a Python 2->3 situation, but it seemed like they didn't quite achieve that.
    • dkarl 92 days ago
      I think you should read this report. They made heavy use of many advanced features of Scala 2. Few codebases look like this (and very, very few need to) yet they were able to do it.

      Moreover, they didn't need to do it. What makes it similar to the Python 2 -> 3 situation is the lack of urgency to migrate, because nobody suffers for not migrating. That's a good thing.

      • merb 92 days ago
        Most people used advanced features, even if they were hidden behind libraries. Even if you’ve just had a codebase which only used playframework.
        • jodersky 92 days ago
          The article mentions they used an experimental language feature, which is enabled via a special compilation flag and came with a big warning from the start that it was in fact experimental and could be removed any time. I highly doubt that most people use any libraries that use those.

          As a side note, I've personally had the experience of migrating several projects to Scala3 (when it was still called Dotty), and never had any issues with 3rd party dependencies, since Scala 3 is binary-backwards compatible with Scala 2.13

        • noelwelsh 92 days ago
          If they are in libraries it doesn't matter, because you can use Scala 2.13 code in Scala 3.
        • AlexITC 92 days ago
          It definitely took a while for most libraries to catch-up with Scala 3, now, I don't see anything is missing in the main area I work with (web development), playframework already works for Scala 3.
      • foolfoolz 92 days ago
        i was surprised to see such advanced type features. i worked at a large scala company. we wouldn’t let most of this stuff through code review. it generally is the kind of magic that saves a tiny amount of code at a high cost of complexity. sounds like this was the authors pet project and wanted to explore instead of write maintainable code
    • kokada 92 days ago
      I don't know, if anything the Scala situation seems much worse than the Python situation. The language looks completely different and there is no easy migration path (not that Python had one, but at least the language was almost the same and you could with some effort write code that worked in both versions).

      We are in Scala 2.13 and while there are talks about migrating there is no actual plan. Looking at this blog post the situation seems to be more dire than I initially expected. I think we will only end up migrating when the situation becomes unsustainable (libraries stop supporting Scala 2).

      • adamwk 92 days ago
        Odersky forcing through major syntax changes for Scala 3 was such an unforced error. It's baffling add new syntax on top of major semantic changes to the type system.
        • hawk_ 92 days ago
          Stroustrup said "There's two kinds of PLs, ones that people complain about and ones that nobody uses."

          Odersky made Scala3 become a language that nobody uses and people complain about!

        • threeseed 92 days ago
          Problem is he’s a full time academic.

          So he doesn’t care if this amazing feature he’s invented has no IDE support.

          Or if the Scala tooling ecosystem is so ridiculously poor.

        • Pet_Ant 92 days ago
          But did it provide a gain in power and soundness? There issues with the 2.x system.
          • lmm 92 days ago
            It did, which makes it all the more frustrating that you can't adopt it separately from the syntax and tooling changes.
            • Taikonerd 91 days ago
              But the new syntax is optional, right? So you could upgrade and keep the old syntax? (I'm not a Scala dev, so this is just my impression.)
              • lmm 91 days ago
                Some of the syntax changes are optional, some of them like the _/* change aren't.
          • merb 92 days ago
            Most programming languages have unsound features.
      • sidkshatriya 92 days ago
        I don’t use Scala but it will always be better than Python 2/3 because of compile time type checks. If it compiles it should work. In the case of Python 2/3 you could often encounter upgrade issues during runtime !
        • adamc 92 days ago
          That can happen in Scala as well because of shared binaries, as is reported in this thread.
          • threeseed 92 days ago
            It’s a completely different situation compared to Python.

            With Scala 2.13/Scala 3 they both compile down to an intermediate format called TASTy which allows binary code to be shared. You don’t get the same binary incompatibilities you do with other languages.

          • sidkshatriya 92 days ago
            That is why I said it “should” work. There are always some really weird edge cases. My broader point holds true. Scala upgrade is not even close to Python 2/3 debacle
      • fulafel 90 days ago
        Python had 2to3 and 3to2.
    • AlexITC 92 days ago
      While the tooling isn't perfect, it has improved considerably over the last years, I remember when IntelliJ couldn't deal with Scala 3 but now, it rarely complains.

      Related to Python 2->3, I don't see how Scala 2->3 compares, there are clear migration guides + tools to help re-writing to switch between the new/old syntax, I have done many migrations and I have used these tools since the time when Scala 3 was launched (I admit that I reverted a migration at that time).

  • theLiminator 92 days ago
    Back when I used to use Scala, the biggest PITA was how every minor version bump you'd run into binary version incompatibilities that you'd only run into at runtime. Has that situation changed?

    I've always felt that Scala the language was always pretty nice, but Scala the ecosystem/tooling was moderately painful to work with. It was getting better over time, but they lost all the momentum they had.

    • philipkglass 92 days ago
      Yes, that's one of the big improvements in Scala 3.

      https://docs.scala-lang.org/overviews/core/binary-compatibil...

      For Scala 3, the minor version is the second number in a version, e.g., 2 in v3.2.1. The third number is the patch version. The major version is always 3.

      Scala 3 guarantees both backward and forward compatibility across patch releases within a single minor release (enforcing forward binary compatibility is helpful to maintain source compatibility). In particular, this applies within an entire Long-Term-Support (LTS) series such as Scala 3.3.x.

      Scala 3 also guarantees backward compatibility across minor releases in the entire 3.x series, but not forward compatibility. This means that libraries compiled with any Scala 3.x version can be used in projects compiled with any Scala 3.y version with y >= x.

      In addition, Scala 3.x provides backward binary compatibility with respect to Scala 2.13.y. Libraries compiled with Scala 2.13.y can be used in projects using Scala 3.x. This policy does not apply to experimental Scala 2 features, which notably includes macros.

    • jeremyjh 92 days ago
      It still seems bizarre to me that the Java ecosystem relies upon code-sharing through precompiled binary packages. Compared to for example Rust or Elixir where you only download source and build it locally so that everything is built with the same compiler and environment. This makes it absolutely trivial to debug your dependencies and even fork them when necessary. Most Java programmers wouldn't ever dream of doing that.
      • phendrenad2 85 days ago
        Give it another look, it's actually quite nice. The issue you find with it doesn't come up that often in practice. Most of the time (99.9+%) you can find the source code to a specific JAR easily. Want to fork or modify? No problem, just edit he code, compile a new JAR, drop it somewhere. Done. It's like if the intermediate code to your favorite language's JIT were shippable (I'm actually surprised more languages don't do this).
      • senorrib 92 days ago
        That's actually a major drawback on Rust to be adopted in enterprise settings. Any GPL library statically compiled would force the entire codebase to be licensed under GPL as well.
        • dtech 91 days ago
          Whether it's source or a binary doesn't matter. You aren't allowed to use a compiled GPL library in non free code. LGPL was specifically made for that case.
        • jeremyjh 92 days ago
          GPL can contaminate you when shared as a dynamic library under certain circumstances. But that doesn't matter, since there are few mainstream libraries in these communities licensed as GPL. Nearly all of it is MIT or Apache.
          • imtringued 91 days ago
            There is no such thing as contamination.

            GPL code doesn't change the license of your code. It only prevents you from using GPL code from your code.

            • jeremyjh 91 days ago
              This is a distinction without a difference. If I must use it, I’d have to GPL my code.
      • rat87 91 days ago
        Why? It makes a ton of sense. Its been a while but I'm pretty sure decompilation leads to much higher level/understandable code in java/c#. Good enough to step into and debug libraries.

        And given how fragile/unreproducible it is you almost never want to modify lines in a dependency. In python I'd make a wrapper or monkey patch it instead of modifying the dependency(Or if you need to actually for the library and add it to the dependenies). Unless it was blocking a one of task that I needed done right away.

      • Kwpolska 91 days ago
        Java IDEs can debug third-party code just fine with decompilation. C# IDEs can get the original source code (https://www.jetbrains.com/help/rider/Debugging_External_Code...). Having to build all dependencies would be slower with no significant benefit, especially since the code compiles to bytecode, not native code. Forking is also doable, e.g. with an internal package feed (and you don’t need to integrate your build stuff with theirs).
      • dingi 91 days ago
        Isn't this due to inherent limitations of native binaries? Java has very few native dependencies, so its trivial to do binary dependencies. Besides, most packages in maven central have their sources in there as well. You can easily download the source package and let the debugger use that.
        • jeremyjh 91 days ago
          No, had nothing to do with native dependencies, they are even more rare in Elixir than Java. It’s simply a different choice in the design.

          I know that I can step into a source package with the debugger, but editing that source and rebuilding doesn’t compile the change into my build does it? The last step of debugging is fixing the code, its much more convenient to first try this in the same project where you encountered it.

    • dionian 92 days ago
      yes, and you can even use 2.13 binaries in 3
  • codr7 92 days ago
    That's how I learned to do migrations/major refactoring from my mentors back in the days.

    First brute force it, observe but don't panic, until you don't get any further.

    Then start over and do it properly.

  • philipkglass 92 days ago
    This is a good report. I started a project last year on Scala 2.13, but had all Scala 3 compatibility features/warnings enabled from the beginning. It sounds like it should be an easy upgrade in the future as long as I don't rely on macros or libraries that rely on macros. I've tried to stick to libraries that already have Scala 3 releases or that come from plain Java.
    • noelwelsh 92 days ago
      It doesn't matter if libraries rely on macros because 1) you only depend on their compiled output and 2) you can use Scala 2.13 code from Scala 3. That said, the vast majority of the open source ecosystem has Scala 3 releases by now.
    • rendaw 92 days ago
      Is it recommended to start with Scala 2 instead of 3 right now?
  • danielciocirlan 91 days ago
    This is a good report.

    Scala 3 is really what Scala was supposed to be. The language is just about perfect, and the most important and popular libraries and tools (Cats/Cats Effect, ZIO, Play Framework, Akka/Apache Pekko) are all supporting the new version for years already.

    It's really a shame that IDE support has yet to catch up and the dev experience is frustrating at times, but I'm using Scala 3 for everything I can.

    • Bgd1 90 days ago
      Totally agree. I'm surprised that the new scala-cli is almost not mentioned at all in other comments. To me this is a game changer and the best in class. I don't think I've seen anything that comes close to its power and ease of use in other programming language SDKs.
    • KajMagnus 91 days ago
      > The language is just about perfect

      Yes totally lovely :- ) And the best std lib? (On shared 1st place I'd guess, Rust looks nice too)

      I just miss better debugging of async code, so I could see the execution context in other threads earlier in the "async call stack".

  • lopatin 92 days ago
    I only allow myself to use Scala these days if follow some rules: no sbt (just Maven) and no Scala libraries (just Java ones). I never used fancy stuff like Cats anyways. Curious to hear who actually does, and for what.
    • jim-jim-jim 92 days ago
      This thread is interesting; so many tools and libraries referenced that I am not familiar with at all. I think some of us are writing very different languages.

      I've used Scala my entire career at multiple companies, and Typelevel has been the default at all of them. I'm not even entirely sure where Scala ends and Cats begins, so it's hard to identify what's "fancy", let alone justify it. I do like IO, and monad transformers. I think neither of those are native. Flat code tends to be maintainable.

      From my perspective, fully baked frameworks and ORMs are what's "fancy" (a readability nightmare). I don't know if it's a cultural thing, but Scala codebases that go hard on FP tend not to introduce these, which I appreciate. Pick your poison I guess.

    • threeseed 92 days ago
      I use ZIO (https://zio.dev) and nothing really like it exists on any platform.

      You can wrap any computation in a single ZIO object e.g. normal, callback, future, promise etc. Which you can then chain together in different ways e.g. run them in parallel, sequentially, race them against each other and kill the loser, schedule in elaborate ways, run with a timeout and then run another if it’s exceeded etc.

      And it will execute this either using normal or virtual threads i.e. fibers without locks so it’s extremely fast.

      But the incredible part is that it does all of this whilst seamlessly handling every type of error. Which if you’ve ever written complex concurrent code is extremely hard to get right.

      • KajMagnus 91 days ago
        Now I feel curious about what do you build that makes that much use of parallel computations, races and killing the loser, etc?
      • pas 92 days ago
        EffectTS? :)
    • jodersky 92 days ago
      This might be a bit of a shameless plug, but because you ask :)

      Regarding no sbt, I would highly recommend to have a look at the mill build tool https://mill-build.org. I personally find it very pleasant to use as a replacement for sbt, mostly because of the following points:

      - it uses regular Scala code to define a build

      - it isn't DSL-heavy like sbt, which means it's A) easy to debug by simple searching, and B) anyone unfamiliar can get a vague idea of what's going on at a first glance

      - it is designed around a generic task graph and isn't centered around the JVM world (disclaimer: I'm helping with development, and recently first-class support for Python and JavaScript projects was added)

    • lmm 92 days ago
      I use cats so that I can write custom effect/wrapper types for e.g. "must happen in database transaction" or "has audit log" or "requires this level of access". (I'd also flag up the free monad, which is like a generic version of the command pattern - you just write your leaf action types and you get a command object for, well, free). Essentially, anything that you might think of using an annotation/AOP pointcut/reflection for, in Scala you can do it with plain old refactor-safe code and have it checked at compile time rather than runtime.
    • aeroevan 92 days ago
      I don't really mind sbt, but we migrated off maven a while back for gradle for java projects. There are some crazy sbt build scripts but it's fairly easy to keep things sane, but maybe the fact that sbt builds can look so different is an issue.

      I really like the simplicity of the com-lihaoyi ecosystem but I also enjoy cats/fs2 and friends on occasion.

    • AlexITC 92 days ago
      sbt is way better than what it used to be, also, check-out scala-cli which is very nice.
  • whoodle 92 days ago
    I currently work at a company who is primarily writing in Scala. I really like Scala but assume my next role won’t be in that. Are my two best options Rust and Java if I want to keep some of the typing, functional style, and pattern matching while also moving to a more popular language?
    • colonial 92 days ago
      Seconding the sibling comment re: Kotlin. I haven't worked much with it personally, but I've heard from plenty of people that it strikes a good balance between Java being... Java and Scala's floundering.

      Rust also checks your feature boxes, but staying in the JVM-verse is almost certainly the safer bet unless you end up really needing fast native binaries that aren't a chore to code.

    • lyall 92 days ago
      Kotlin is gaining steam in the Java world. We're moving to make it our default server-side language at my company instead of Java. Given its great Java interop, you can basically think of it as a modern, more functional Java that doesn't have multiple decades of baggage associated with it. I highly recommend considering it in any place you'd consider Java.
      • spockz 91 days ago
        Now that Java has caught up a lot with records, value classes, project loom (virtual/green threads), pattern matching. What is left?

        Scala has the better type system with union types and effects (a more generic way of having “throws”.)

        Kotlin has a nicer way of dealing with optional values with the ? operator.

        What’s left is the syntax. Or am I missing something? These alone do not seem to justify moving an organisation.

        • imtringued 91 days ago
          Java still sucks.

          Where are Java properties, so people can stop writing the silly getter setter nonsense?

          Where are default parameters and named parameter calls?

          Where is the null friendly field access operator ?. ?

          Where is the convenient list and hashmap literal syntax?

          Why is the stream API so verbose? Why not offer a third generation collections API?

          Where are the sane ORMs?

          Now here is some JVM hate:

          How do I make sure that my application starts up quickly and isn't slow the first time you're accessing a web page after a restart?

          How do I make sure that I don't need a 2GB RAM server for a simple web app? Cloud providers are stingy with RAM, so this adds up, even though RAM costs are an insignificant part of overall server costs.

          How do I write a CLI app with the JVM? You don't.

          So yeah, Java is in this uncanny valley where it is either obsoleted language wise by JVM languages from 2009 and runtime obsoleted by languages like Rust, where you trade off a bit of convenience, which Java by the way does not have either, for a bit of performance.

    • thinkharderdev 91 days ago
      I spent 10 years or so mostly writing Scala and now am entirely using Rust. I found the transition really easy. Where I work now has historically been a Scala shop and is moving more and more towards Rust as the default. In my experience engineers who are seasoned Scala devs pick it up very quickly
  • fulafel 91 days ago
    It will be interesting to see how Clojure and Scala do in the longer run in the industry oriented FP languages scene. I wonder if there's any data points around that could tell a tale.
  • virtualwhys 92 days ago
    Migrated a Scala 2.8(!) era codebase to Scala 3.

    As OP explains, macros and abstract type projections tend to be the biggest pain points in complex applications; otherwise, with Scala Rewrite tool it's pretty straightforward.

    I think it's more inertia than anything else that more Scala 2 companies don't migrate.

    Unpopular opinion, but setting a Scala 2 sunset time would spur companies into action :)

    As it stands Akka (previously Lightbend, previously TypeSafe) is the maintainer of Scala 2, and derives part of its revenue from Scala 2 support contracts so there's even less incentive to migrate when there's no EOL date as Python 2 (eventually) had.

    • hocuspocus 92 days ago
      While a bit late to the party, Akka on Scala 3 is perfectly viable nowadays, and they have a couple employees contributing to Scala 3.

      The bigger issue comes from Databricks being the biggest Scala Center sponsor while holding the entire ecosystem back, for instance with their managed Spark runtime still on 2.12.

    • rat87 91 days ago
      As someone who has done a couple of python 2 to python 3 migrations I'm still surprised that there isn't someone big selling support/security patches for python2. There must be a lot of giant corporate python2 code bases that were a lot harder to port and where it was much less acceptable to find random 2to3 bug I'm production then the QA and build system codebases I ported
  • dylanowen 92 days ago
    This is a great write up! For people using gradle to compile scala (definitely not my first choice) the initial hurdle to migrating individual modules has been fixed! I'm guessing it'll be in gradle 8.13 https://github.com/gradle/gradle/pull/31118
  • paulddraper 92 days ago
    I didn't know the ecosystem wasn't on 3.

    It was released May 2021.

    It is a big change though.

    • AlexITC 92 days ago
      Most of the ecosystem is on Scala 3, I think Spark would be the biggest piece pending to upgrade.
      • aeroevan 92 days ago
        With spark 4 defaulting to scala 2.13, that does move things in the right direction since the 2.13 -> 3 interop is possible
  • rr808 92 days ago
    Currently work on a Scala/Spark project as part of our work. Everyone hates it except the one guy who knows it well, but for most people who spend most of their time doing imperative languages its just too much of a mind jump. Hopefully soon we'll be on a new big data platform soon and we wont have to deal with a migration like this.
  • spockz 91 days ago
    As I mentioned deeper in the thread, https://news.ycombinator.com/item?id=42969519, Java seems to have caught up with Kotlin and Scala language wise. (With Scala3 having the most extensive type system.)

    The ecosystem also seems to have petered out. Akka, spark, and flink used to be reasons to do scala. But they have decent java interfaces now.

    I’ve had too much struggles convincing colleagues that actually more information in the type is convenient. It seems like the same religion of untyped vs typed.

    What is left as reasons to choose for scala or Kotlin?

    • dtech 91 days ago
      I think you're over-selling the parity.

      Value based classes aren't definable by your own code yet. Records are severely underbaked, unless I missed it there isn't even a copy method yet, and those are essential for working with immutable data.

      Then there's still a lot of features that Java is sorely lacking like extension methods, named parameters and delegation, even though they have proven themselves in multiple other programming languages by now.

  • slavomirvojacek 92 days ago
    I am wondering whether with GenAI, migrations like this one will be less and less painful, and therefore more people will be able to migrate to newer technologies/versions sooner and quicker.
    • aiono 92 days ago
      Why use GenAI for this use case? Instead you can write transformers from one syntax to another syntax that will not hallucinate and work correctly every time. The conversion is well-defined.
      • nsonha 92 days ago
        Or use GenAI to write the codemod :)
  • aristofun 91 days ago
    Scala has some nice and cool vibes and features to it.

    But that is where good parts end.

    From the POV of real world boots-on-theground software challenges and developers it is a poorly designed, overengineered and overrated piece of complexity.

    Complexity disconnected from reality of software engineering as a tool to serve business needs.

    I can explain why this happens but I don’t want to get downvotes. People hate hearing bitter truth:)

  • cbeach 92 days ago
    Very useful document, thanks Pierre!

    Our company is still on 2.13 and probably will be for a long time. The reality is that we need rock-solid library support across all transitive dependencies, and mature battle-tested tooling.

    I like that the Scala language continues to improve, but its appeal in real-world enterprise applications took a hammering due to the backwards-incompatible changes in Scala 3, shaky tooling and ecosystem issues.

    Also the elephant in the room - the Scala Center and toxicity within the Scala community.

    The Scala Center Executive Director is a political sciences graduate with no commercial Scala experience, who gave this expletive-laden sexualised rant at a Scala conference:

    https://x.com/jdegoes/status/1633888998434193411?s=46&t=V_LF...

    When this ugly performance was called out by a member of the Scala ecosystem, it was the guy that called it out that got brigaded and cancelled, while the executive director Darja Jovanovic was defended by the community, and remains in place.

    And then there's Scala Center Community Representative Zainab Ali, who led an orchestrated witch hunt against a contributor to the Scala ecosystem. She ended up in the UK High Court for her role in this, and admitted fault (defamation) and settled.

    https://pretty.direct/statement

    Like the executive director, the community rep remains in place at Scala Center:

    https://www.scala-lang.org/ambassadors/

    • pie_flavor 92 days ago
      Organizational political drama is just about the least relevant thing possible to whether you update from Scala 2 to Scala 3. The ultimate fate of Jon Pretty does not impact the behavior of macro annotations.
    • michaelmrose 92 days ago
      The rant was

      "whoever it is I challenge that person to grow some fucking male anatomy and come and speak to me ... you little female anatomy plural you are just fucked up"

      Fairly shocking language but also pretty devoid of context although I come to suspect it has to do with people talking behind her back regarding the second part.

      The second case appears to be a fellow who was publicly libeled professionally ruined and then sued the shit out of the offender. According to him this was solely because he had dumped community rep. In the settlement they admitted that they had circulated the letter claiming he was a serial sexual harasser based on no evidence but unverified claims. Settled for a rather paltry sum of £5000.

      So community rep and contributor split for whatever reasons and then she shit talks him spreading possibly true likely untrue claims that he's a particular type of jerk which she likely can't back up with anything like evidence other than her own now terminated relationship.

      If they didn't fire her they probably believe that she was in the right but settled.

      No part of this probably belonged as part of professional life and should have stayed between them. I don't believe enough evidence exists for people who don't know either party to declare anyone a villain and if I had any professional involvement with either I would simply pretend none of that existed and move on.

      If I was merely using the code I would definitely ignore it.

      • tsss 92 days ago
        This sort of behaviour is so pervasive among certain influential circles, which makes it hard to ignore. Thankfully, the conflict seems to have died down a bit in the last 2 years and I'm looking forward to changes in Scala 3 that make the libraries that those people develop mostly superfluous.
    • paulddraper 92 days ago
      Most of the Scala ecosystem exists outside of the Scala Center.

      Same with Rust, Go, and any other language.