BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage News Road to Scala 3: Release Candidate Available

Road to Scala 3: Release Candidate Available

This item in japanese

Scala 3.0.0 is scheduled for release in early-mid 2021, and the first release candidate is now available. Scala 3 incorporates many changes and is based on Dotty, a new compiler using the internal data structures of Document Object Types (DOT). Scala 3 is a backward binary compatible version with Scala 2.13.

The Dotty code base is almost half the size of the current nsc compiler and promises an improvement in performance. In development for the past eight years, new features in Dotty include new types, improved enum handling and metaprogramming.

The timeline for the Scala 3 release can be seen in the following diagram from the Scala Lang "Crossing the Finishing Line" blog post.

As stated on the website, the development of Scala 3 is focused on three main goals:

  • Strengthen Scala's foundations. Make the full programming language compatible with the foundational work on the DOT calculus and apply the lessons learned from that work.
  • Make Scala easier and safer to use. Tame powerful constructs such as implicits to provide a gentler learning curve. Remove warts and puzzlers.
  • Further improve the consistency and expressiveness of Scala's language constructs.

Scala 3 offers support to ease the migration from version 2. A migration guide is available and the compiler can automatically convert existing code to use some of the new Scala 3 features.

One of the new features is improved enum support. Traditionally defining an enum in Scala 2 is verbose. Consider the following example:

sealed trait Direction
case object North extends Direction
case object South extends Direction

Scala 3 introduces a more concise syntax with enum types:

enum Direction:
   case: North, South

Curly braces in Scala define group expressions:

sealed trait Employee { 
   def number: String 
}

The new significant indentation based (SIB) syntax allows developers to replace the curly braces and the Dotty compiler can automatically convert existing Scala code to the new SIB syntax. When compiling with dotc -indent -rewrite, the original Employee sealed trait is converted to:

sealed trait Employee 
   def number: String 

It’s also possible to revert back to the original syntax with the command dotc -no-indent -rewrite.

The new control syntax is another syntax change specifically designed for control expressions. For instance, until now, conditions for if statements and for loop enumerations were enclosed in parentheses:

if (i < 3) println("smaller") else println("bigger")
for (i <- 0 until 3) println(i)

With dotc -new-syntax -rewrite, these control expressions are rewritten without parentheses by using the then and do keywords:

if i < 3 then println("smaller") else println("bigger")
for i <- 0 until 3 do println(i)

As with SIB, it’s possible to revert back to the old syntax by using dotc -old-syntax -rewrite. The compiler is able to automatically convert to the new SIB control syntaxes. However, those are separate steps, which cannot be executed at once.

Inlining is a new metaprogramming feature to achieve better performance during compile time. Scala 3 introduces the inline soft keyword which guarantees inlining is executed instead of being a best-effort. This is different when using the final keyword, which is based on a best-effort. After a constant is inlined, then other constants based on the inlined constant are computed compile-time:

inline val answerToEverything = 42
val doubleTheAnswerToEverything = 2 * answerToEverything

Inlining a method is a new compiler feature that replaces the method call with the body of that method. Better performance is achieved as this eliminates the need for the method to push all of its parameters to the stack. The same inline soft keyword is used to inline a method:

inline def print(s: String): Unit =

It’s possible to further improve the performance by inlining parameters, conditionals and method overriding.

Inlining is used by Scala 3 Macros which replaces the experimental macros of Scala 2. Macros treat programs as data and manipulate them.

Several new types have been introduced in Scala 3. For instance, the & operator is used on types to create an intersection type. The intersection type Plane & Car contains all the members of Plane and all the members of Car as shown in the following example:

trait Car:
   def drive = "Driving"

trait Plane:
   def fly = "Flying"

def print(v: Plane & Car): Unit =
   println(v.drive)
   println(v.fly)

Union types use the | operator. The union type Person | Company contains all values of Person and all values of Company as shown in the following example:

def isPersonOrCompany(t: Person|Company) = t match
  case p: Person(firstName) => findFirstName(firstName)
  case c: Company(registrationNumber)  => findRegistrationNumber(registrationNumber)

Some features have been removed in Scala 3. For instance, the Symbol literal should be replaced by a plain String literal or a dedicated class. Also, the new control syntax has changed the meaning of the do keyword. The original construction of do <body> while (<cond>) should be replaced with while ({ <body>; <cond> }) ().

More details on Scala 3changes and new features can be found in the documentation. A complete overview is also available on the Scala 3 website.

Rate this Article

Adoption
Style

BT