a tour of Scala 3


1.A Tour of Scala 3 Martin Odersky Scala Days Lausanne June 2019

2.10th Anniversary Edition of ScalaDays It all started here in 2010

3.10th Anniversary Edition of ScalaDays It all started here in 2010

4.Some curious parallels between now and then What was new in 2010? Collections in Scala 2.8 And today? Scala 2.13, with even better collections! First redesign since 2010 100% CanBuildFrom free!

5.Scala 2.13 • Redesigned collections (à talk by Stefan Zeiger, Wed 17.45) • Updated futures implementation (à talk by Viktor Klang, Wed 14.30) • Language changes: § literal types § partial unification (SI-2712) on by default § by-name implicits § macro annotations § many polishings in details Merged over 1500 pull requests from 162 contributors

6.More curious parallels between now and then • Scala 2.8 had some breaking language changes. • Should have been named 3.0. • But we already talked about it as 2.8, felt that it was too late to change. • Now in 2019, Scala 3.0 has (almost) arrived!

7.Roadmap June 2019 All features fleshed out, with Scala 2.13 implementations in Dotty 0.16+ Fall 2019 Feature freeze, Scala 3.0 M1 stabilization complete SIP process write spec, user docs migrate open-source ecosystem flesh out tests, community build compatibility and migration tools Fall 2020 Scala 3.0 final Scala 2.14

8.A Tour of Scala 3

9.Best of Scala 3 What are Scala-3’s Nicest Features? • For beginners • For everyday coding ? • For experts ? I’ll give my personal ranking ? of the top 3 of each category. I also did a Twitter survey and will report on that.

10.Nicest Features for Beginners? • At that level, most of the language stays the same • But there are nevertheless a few improvements worth mentioning … ?

11.#3: Drop New class StringBuilder(s: String) { def this() = this("") } StringBuilder("abc") // same as new StringBuilder("abc") StringBuilder() // same as new StringBuilder() • new can be omitted from almost all instance creations. • Only needed to disambiguate in an apply method. • No need to define a case class anymore just to get nice constructor calls.

12.#2: Toplevel Definitions package p type Labelled[T] = (String, T) val a: Labelled[Int] = ("count", 1) def b = a._2 def hello(name: String) = println(i"hello, $name) All kinds of definitions can be written on the toplevel. Package objects are no longer needed, will be phased out.

13.#1 Enums enum Color { case Red, Green, Blue } Simplest way to define new types with a finite number of values or constructors.

14.#1 Enums enum Planet(mass: Double, radius: Double) extends java.lang.Enum { private final val G = 6.67300E-11 def surfaceGravity = G * mass / (radius * radius) case MERCURY extends Planet(3.303e+23, 2.4397e6) case VENUS extends Planet(4.869e+24, 6.0518e6) case EARTH extends Planet(5.976e+24, 6.37814e6) case MARS extends Planet(6.421e+23, 3.3972e6) ... } can have parameters can define fields and methods can interop with Java

15.#1 Enums enum Option[+T] { case Some(x: T) case None } can have type parameters, making them algebraic data types (ADTs)

16.#1 Enums sealed abstract class Option[+T] object Option { case class Some[+T](x: T) extends Option[T] object Some { def apply[T](x: T): Option[T] = Some(x) } val None = new Option[Nothing] { ... } } compile to sealed hierarchies of case classes and objects.

17.#1 Enums enum Tree[T] { case True extends Tree[Boolean] case False extends Tree[Boolean] case IsZero(n: Tree[Int]) extends Tree[Boolean] case Zero extends Tree[Int] case Succ(n: Tree[Int]) extends Tree[Int] case If(cond: Tree[Boolean], thenp: Tree[T], elsep: Tree[T]) extends Tree[T] } can be GADTs (generalized ADTs). à cases can extend the base type with different type arguments.

18.The public vote:

19.Why Enums? • Lots of use cases, and they are becoming more common. • Avoids boring, repetitive boilerplate. • Can grow from very simple to very powerful.

20.Nicest Features for Everyday Coding? • There are lots of candidates. • Hard to come up with a shortlist. ?

21.#3 Union Types case class UserName(name: String) case class Password(hash: Hash) def help(id: UserName | Password) = { val user = id match { case UserName(name) => lookupName(name) case Password(hash) => lookupPassword(hash) } ... } Provide ad-hoc combinations of types Subsetting = Subtyping No boxing overhead

22.#3 Union Types type Command = ”Click" | ”Drag" | ”KeyPressed" def handleEvent(kind: Command) = kind match { case “Click" => MouseClick() case ”Drag" => MoveTo() case ”KeyPressed" => KeyPressed() } Work also with singleton types Great for JS interop

23.#2 Extension Methods object StringOps { def (s: String) * (x: Int): String = if (x <= 0) “” else s * (x - 1) ++ s } import StringOps._ "hello" * 3 Replace implicit classes Make it easier to add methods to existing classes.

24.#1 Delegates trait Ord[T] { def (x: T) compareTo (y: T): Int def (x: T) < (y: T) = x.compareTo(y) < 0 } delegate IntOrd for Ord[Int] { def (x: Int) compareTo (y: Int) = if (x < y) -1 else if (x > y) +1 else 0 } def maximum[T](xs: List[T]) given Ord[T] = xs.reduce((x, y) => if (x < y) y else x) Replace “implicit” as a modifier Express intent instead of mechanism

25.#1 Delegates trait SemiGroup[T] { def (x: T) combine (y: T): T } trait Monoid[T] extends SemiGroup[T] { def unit: T } delegate for Monoid[String] { def (x: String) combine (y: String) = x.concat(y) def unit = "" } def sum[T: Monoid](xs: List[T]): T = xs.foldLeft( the[Monoid[T]].unit )(_.combine(_)) Work out of the box with extension methods Provide a nice syntax for typeclasses

26.#1 Delegates tame implicit conversions implicit def intToStr(str: String): Token = new Keyword(str) What’s wrong with this? It’s too easy to write compared to how dangerous it is. Implicit as a modifier will go away, and with it this kind of conversion.

27.#1 Delegates The only way to express implicit conversions is as a delegate for a standard Conversion class: delegate for Conversion[String, Token] { def apply(str: String): Token = new KeyWord(str) } Or, using an alias delegate: delegate for Conversion[String, Token] = new KeyWord(_)

28.The public vote:

29.Why Delegates? Implicits are Scala’s most distinguished feature. But they are also the most controversial one. Delegates are a simpler and safer alternative. They • emphasize intent over mechanism • make idea of term inference more accessible • discourage abuses