1 of 21

Scala 3 Features

Part 1 - Clint Combs

@ClintCombs

2 of 21

Dotty

  • The next generation Scala compiler project
  • Started in 2013 to develop compiler technology and language ideas
  • Now the basis for Scala 3

3 of 21

Scala 3 Feature Groups - 68 Changes

  • New Types (5)
  • Enums (2)
  • Contextual Abstractions (11)
  • Metaprogramming (5)
  • Other New Features (12)
  • Changed Features (17)
  • Dropped Features (16)

Features Overview

4 of 21

Scala 3 Roadmap Update

  • Current Release is Scala 2.13 (2.13.1)
  • There will not be a Scala 2.14 release!
  • First 3.0 release candidate by the end of 2020
  • Scala 2 Roadmap Update: the Road to Scala 3

5 of 21

December 3, 2008

6 of 21

December 3, 2008�Python 3 Released

7 of 21

Python 3 All Over Again? No

“Our strategy for making your upgrade predictable and manageable comprises:

  • There will be no “silent” breaking changes in run-time behavior. The standard library is shared. The ABI of Scala 2.13 and 3.0 will be the same: the encoding of key language constructs, such as traits and lazy vals, are shared.
  • Scala 3 is backwards compatible with Scala 2, except for a few deprecated features that are being dropped. The Scala standard library already cross-compiles between the two versions. So can your project.
  • As always, the type checker has your back: changes are often caught by the compiler as type errors or migration warnings.”

8 of 21

Migration - Scala 2.12/2.13 to Scala 3.0

  • Scala 2.x releases are not binary compatible (_2.11, _2.12)
  • Enable scalac warnings
  • Start cross compiling with Scala 2.13
  • Scala 2.13 and 3.0 standard libraries are the same library
  • Use scala-collection-compat to ease transition from 2.12 -> 2.13 -> 3.0
  • TASTy and Binary Compatibility
    • Scala 3.x releases maintain binary compatibility via TASTy
    • “There is no need for library maintainers to re-publish when a new Scala 3.x minor release becomes available.”
  • YouTube: Designing libraries for source and binary compatibility

9 of 21

TASTy

  • Scala TASTy is the analogue of Java byte code
  • Encodes complete semantics of source, comments, etc.
  • Typed Abstract Syntax Trees
  • Binary encoding of the syntax tree after the typer compiler phase
  • Provides binary compatibility across minor releases

10 of 21

Features...

11 of 21

Extension Methods

def (c: Coach) age: Int = Period.between(c.birthDate, LocalDate.now).getYears

val age = coach.age

// extension methods and operators

case class Color(rgb: Int)

def (c: Color) & (other: Color): Color = Color(c.rgb & other.rgb)

  • Add methods to a type after it is defined
  • This syntax is changing in the upcoming 0.22 release of Dotty

12 of 21

Enumerations

enum Position(val numeric: Int) {

case Pitcher extends Position(1)

case Catcher extends Position(2)

case FirstBase extends Position(3)

case SecondBase extends Position(4)

case ThirdBase extends Position(5)

case Shortstop extends Position(6)

case LeftField extends Position(7)

case CenterField extends Position(8)

case RightField extends Position(9)

}

13 of 21

Algebraic Data Types

  • “a closed set of possible values under one, common interface”
  • Sums and Products
  • Scala 2 (sealed traits and case classes/objects)
  • Scala 3 (enums)

enum Color(val rgb: Int) {

case Red extends Color(0xFF0000)

case Green extends Color(0x00FF00)

case Blue extends Color(0x0000FF)

case Mix(mix: Int) extends Color(mix)

}

14 of 21

Intersection Types

  • Type A&B is both A and B at the same time
  • & will ultimately replace the with clause used for extending multiple traits

trait Employee {

def firstName: String

def lastName: String

def age: Int

}

trait SoftballPlayer { def position: Position }

case class Player(firstName: String, lastName: String, age: Int, position: Position)

extends Employee with SoftballPlayer

val p: Employee & SoftballPlayer = Player("John", "Doe", 30, Pitcher)

15 of 21

Union Types

  • A|B contains all values of type A and all values of type B; A|B === B|A

val team = List[Player](

Player("John", "Doe", 30, Pitcher), Player("Catcher", "Doe", 31, Catcher))

val coach = Coach("Earl", "Monroe", LocalDate.of(1967, 3, 10))

val entireTeam: List[Player | Coach] = team ++ List(coach)

def [A <: Player | Coach](team: List[A]) averagePlayerCoachAge: Double = {

team.map {

case Player(_, _, age, _) => age

case c: Coach => c.age

}.sum.toDouble / team.size.toDouble }

16 of 21

Explicit Nulls

  • Address Tony Hoare’s “Billion Dollar Mistake” from ALGOL
  • Option types have been successful
  • Explicit Nulls
    • Aim to fix the null issue using union types
    • Will initially be enabled via a compiler flag:�-Yexplicit-nulls

17 of 21

Scala Type Hierarchy

18 of 21

Scala Type Hierarchy with Explicit Nulls

19 of 21

Explicit Null Type Syntax

val s1: String = “test”�val s2: String = null // type error!�val s3: String | Null = “test”�val s4: String | Null = null��// type alias�type StringOrNull = String | Null

20 of 21

Explicit Nulls: Calling Existing Code

  • A lot of Scala code outlaws the use of null via sbt-scalastyle rules
  • Most Scala code uses Option[T]
    • val s: Option[String] = Some(“test”)
    • val x: Option[String] = None
  • Java code is more likely to return null
  • lombok’s @NonNull declares that Java methods will not return null
  • Java method returning String:�def getString1(): String | UncheckedNull
  • Java method returning String and annotated with @NonNull:�@NonNull def getString2(): String
  • type UncheckedNull = Null

21 of 21

Coming Soon...

Scala 3 Features - Part 2