We love scala 3 - Let's migrate!

Ingar Abrahamsen
Ingar Abrahamsen
Published 2024-06-06
scalacode

I have a confession to make; I find Scala 3 awesome and I love it! I am a lazy developer; I love a good codebase, and I absolutely hate doing boring chores. Manual labor is not for me. Let's automate it ;-). The scala team and the community have enabled us to automate the migration and in this post we will take it one step further.

Prior art

Before you start migrating you should be aware of tooling-tour. It contains a lot of tips and tricks and it's prerequisite before moving on.

If you're dropping Scala 2 support then we can get some help from the compiler to do some syntax migration. Cool! We're over to Scala 3 and we are using syntax like if true then "yey" else "ney". But what about the new cool syntax like given, using, and derived?

Migrate more syntax

Great news everyone! We have some scala-fix rules at arktekk/scala3-scalafix that you might want to look into. The rules are intended to be used as a once-off. Add the following dependency to scalafix and apply the rules you want to run.

scalafixDependencies += "no.arktekk" %% "scala3-scalafix" % "%version%"

Let's showcase some of the rules. You'll find a complete list of the available rules at arktekk/scala3-scalafix.

SemiAuto

Here's an example where we have defined a circe codec:

case class Person(name: String)
object Person {
  implicit val codec: Codec.AsObject[Person] = deriveCodec
}

New syntax:

case class Person(name: String) derives Codec.AsObject

GivenAndUsing

An example where we used implicit in scala 2 where we replace it with given or using based on the context.

case class Message(m: String)
object Message {
  implicit show: Show[Message] = ???
}
class Printer(implicit console: Console) {
  def print[A](implicit showA: Show[A]): Unit = ???
}

New syntax:

case class Message(m: String)
object Message {
  given show: Show[Message] = ???
}
class Printer(using console: Console) {
  def print[A](using showA: Show[A]): Unit = ???
}

Please note that we might encounter some compile errors after running GivenAndUsing.
It will do 90% of the migration job for you. I'll address this issue in a followup post.

Summary

The new Scala 3 syntax has grown on me and I love it. Having tooling like Scalafix has for me eased the burden on migration. It has its limitations, and we must expect some false-positive-rate for some migrations. We'll take a closer look at one particular limitations in the scalafix post.