Mike Slinn

Scala 3 Major Features

— Draft —

Published 2019-09-07. Last modified 2024-08-12.
Time to read: 3 minutes.

Scala 3 is a complete rewrite of the Scala compiler, using a new theoretical foundation. The Scala 3 microsite is here, and the GitHub project is here. The blog, with links to resources, is here.

This lecture is only meant as a quick preview and will not discuss details.

The Killer Feature

Dotty solves Scala’s binary compatibility problem, so there is no need for 3rd party libraries to be published specially for each version of Scala 3.

Compatibility

  • Scala 3 code can use many Scala 2 libraries because the Scala 3 compiler understands the classfile format for sources compiled with Scala 2.12+. The exception is that Dotty does not support Scala 2 macros, so libraries such as quill won’t work until they are ported to Dotty. The following sample build.sbt shows the magic incantation necessary to make this work. awslib_scala is one of my libraries, and it is cross-published for Scala 2.10, 2.11, 2.12 and 2.13, but not Dotty. Nonetheless the library can be used in a Dotty project:
    val dottyVersion = "0.18.1-RC1"
    val scala212Version = "2.12.9"
    lazy val root = project .in(file(".")) .settings( name := "dotty-cross", version := "0.1.0",
    libraryDependencies ++= Seq( "com.micronautics" %% "awslib_scala" % "1.1.13" withSources(), "com.novocode" % "junit-interface" % "0.11" % Test ).map(_.withDottyCompat(scalaVersion.value)),
    resolvers += "micronautics/scala on bintray" at "https://dl.bintray.com/micronautics/scala",
    // To make the default compiler and REPL use Dotty scalaVersion := dottyVersion,
    // To cross compile with Dotty and Scala 2 crossScalaVersions := Seq(dottyVersion, "2.13.0", scala212Version) )
  • Scala 2 implicits are being replaced by givens; this is dedicated syntax to support typeclasses. Scala 2’s typeclasses must be home-made, while Dotty provides proper support.
  • The implicitly method from Predef (discussed in the Implicit Conversions and Predef lectures of the Intermediate Scala course).
  • Value classes (discussed in the Implicit Values lecture of the Intermediate Scala course) are being replaced by opaque types.
  • Scala 3 and Scala 2 share the same standard library, which means they both use the same collection classes.
  • With some small tweaks it is possible to cross-build code for both Scala 2 and 3. A guide will be published that defines the shared language subset that can be compiled under both versions.
  • The Scala 3 compiler has a -language:Scala2 option that lets it compile most Scala 2 code and at the same time highlights necessary rewritings as migration warnings.
  • The compiler can perform many of the rewritings automatically using a -rewrite option.
  • Migration through automatic rewriting will also be offered through the scalafix tool, which can convert sources to the cross-buildable language subset without requiring Scala 3 to be installed.

Major New Features

The high-level new features are:

Intersection types

Intersection types are similar to Scala 2 trait mixins (which we will discuss in the Scala Traits lecture). This is useful for ad-hoc polymorphism, used in typeclasses.

Scala code
def foo(arg: Serializable & Comparable): Unit

Union Types

Union types are similar to C language structs and form the basis for proper enumerations (Scala 2’s support for enumerations is weak).

Repeated by-name parameters

We will discuss varargs and placeholder splat in the Classes Part 2 lecture, Functions in the Functions are First Class lecture, by name parameters in the Higher-Order Functions lecture of the Intermediate Scala course. In this code, => T* means Function0[Seq[T]].

Scala code
object DaysOfTheWeek{
  def foo(a: => Any*) = ()
  def bar(a: => Any*) = foo(a : _*)
  def baz(a: => Seq[Any]) = foo(a : _*)
bar(???, ???) baz(Seq(???, ???)) }

Trait parameters

Traits will be discussed in the Scala Traits lecture. Dotty changes traits so they are more like abstract classes, discussed in the Classes Part 2 lecture. I’ve wanted this feature many times over the years.

Improved lazy val initialization

Lazy vals work like magic, except when they don’t. Dotty lazy values:

  • Do not deadlock
  • Allow concurrent initialization of independent fields
  • Are thread unsafe by default
  • Are 40% faster to access by default
  • Need @volatile to request thread safety
  • If @volatile is used, 5% faster than Scala 2 (one non-volatile read vs volatile read)

The following code presents a problem for Scala 2.

Scala code
object A {
  lazy val a0 = B.b // <-- Thread 1, grabs lock
  lazy val a1 = 17  // Potential deadlock
}
object B { lazy val b = A.a1 // <-- Thread 2, grabs lock }

Scala 3 solves the problem like this:

object C {
  lazy val a0 = { /* long computation with IO */ } // <-- Thread 1
  lazy val a1 = 42  // <-- Thread 2 will be waiting for Thread 1 to finish
}

Detailed Features

Scala 3’s features are prominently displayed on the microsite; here they are:

See the Scala 3 Reference for a comprehensive list.

Create a Dotty project

SBT works with Dotty just as it does with Scala 2.x. To create a new Dotty project, use the giter8 template called scala/scala3.g8, type:

Shell
$ sbt new scala/scala3.g8
... lots of output ...
A template to demonstrate a minimal Dotty application
name [Dotty Project Template]:
Template applied in /mnt/c/work/experiments/dotty/./dotty-project-template

To create a new Scala 3 project that cross-compiles with Scala 2 use the scala3-cross.g8 giter8 template.

Shell
$ sbt new scala/scala3-cross.g8
... lots of output...
A template to demonstrate a minimal Dotty/Scala 2 cross-compiled project
name [Dotty Cross]:
Template applied in /mnt/c/work/experiments/dotty/./dotty-cross

See the Scala 3 Example Project.


* indicates a required field.

Please select the following to receive Mike Slinn’s newsletter:

You can unsubscribe at any time by clicking the link in the footer of emails.

Mike Slinn uses Mailchimp as his marketing platform. By clicking below to subscribe, you acknowledge that your information will be transferred to Mailchimp for processing. Learn more about Mailchimp’s privacy practices.