Scala 3には多くの変更が組み込まれており、Dottyに基づいている。新しいコンパイラは、Document Object Types (DOT) の内部データ構造を使用する。そのコードベースは現在の nsc
コンパイラのほぼ半分のサイズであり、パフォーマンスの向上が約束されている。過去8年間の開発において、新しい型を含むDottyの新機能は、改善された enum
型の処理とメタプログラミングが含まれる。最初のリリース候補が利用可能になり、バージョン 3.0.0は2021年の初めから中頃にリリースされる予定だ。Scala 3は、Scala 2.13の下位バイナリ互換バージョンだ。
Webサイトに記載されているように、Scala 3の開発は3つの主要な目標に焦点を合わせている:
- Scalaの基盤を強化します。完全なプログラミング言語をDOT計算 (dot calculus) の基本的な作業と互換性を持たせ、その作業から学んだ教訓を適用します。
- Scalaをより簡単かつ安全に使用できるようにします。よりゆるやかな学習曲線を提供するために、implicit のような強力な構造を抑制します。いぼや困惑を取り除きます。
- Scalaの言語構造の一貫性と表現力をさらに向上させます。
Scala 3は、バージョン 2からの移行を容易にするサポートを提供する。移行ガイドは利用可能であり、コンパイラは既存のコードを自動的に変換して、Scala 3の新機能の一部を使用できる。
新機能の1つは、enum
サポートの改善だ。従来のScala 2で enum
を定義するのは冗長だ。次の例を考えてみましょう:
sealed trait Direction
case object North extends Direction
case object South extends Direction
Scala 3では、enum 型
を使用したより簡潔な構文が導入される:
enum Direction:
case: North, South
Scalaの中括弧 (curly brace) は、グループ式を定義する:
sealed trait Employee {
def number: String
}
新しい重要なインデントベース (SIB - significant indentation based) 構文で、開発者は中括弧を置き換えることができ、Dottyコンパイラは既存のScalaコードを新しいSIB構文に自動的に変換できる。コンパイル時に dotc -indent -rewrite
を使用すると、元の Employee
sealed trait は次のように変換される:
sealed trait Employee
def number: String
コマンド dotc -no-indent -rewrite
を使用して、元の構文に戻すこともできる。
新しい制御構文は、制御式用に特別に設計された別の構文変更だ。たとえば、これまで if
ステートメントと for
ループ列挙の条件は括弧で囲まれていた:
if (i < 3) println("smaller") else println("bigger")
for (i <- 0 until 3) println(i)
dotc -new-syntax -rewrite
を使用すると、これらの制御式は、then
と do
キーワードを使うことで、括弧を無くして書き換えられる:
if i < 3 then println("smaller") else println("bigger")
for i <- 0 until 3 do println(i)
SIBと同様に、dotc -old-syntax -rewrite
を使用して、古い構文に戻すことができる。コンパイラは、新しいSIB制御構文に自動的に変換できる。ただし、これらは個別のステップであり、一度に実行することはできない。
インライン化は、コンパイル時のパフォーマンスを向上させるための新しいメタプログラミング機能だ。Scala 3では、ベストエフォートではなくインライン化が実行されることを保証する inline
ソフトキーワードが導入されている。これは、ベストエフォートに基づく final
キーワードを使用する場合とは異なる。定数がインライン化された後、インライン化された定数に基づく他の定数はコンパイル時に計算される:
inline val answerToEverything = 42
val doubleTheAnswerToEverything = 2 * answerToEverything
メソッドのインライン化は、メソッド呼び出しをそのメソッド本体に置き換える新しいコンパイラ機能だ。これにより、メソッドはすべてのパラメータをスタックにプッシュする必要がなくなり、パフォーマンスが向上する。同じ inline
ソフトキーワードを使ってメソッドをインライン化する:
inline def print(s: String): Unit =
パラメータ、条件、メソッドのオーバーライドをインライン化することで、パフォーマンスをさらに向上することが可能だ。
インライン化は、Scala 2の実験的なマクロを置き換えるScala 3のマクロが使用される。マクロはプログラムをデータとして扱い操作する。
Scala 3に、いくつかの新しい型が導入された。たとえば、&
演算子は、インターセクション型を作成するために型で使用される。次の例に示すように、インターセクション型の Plane & Car
には、Plane
のすべてのメンバと Car
のすべてのメンバが含まれる:
trait Car:
def drive = "Driving"
trait Plane:
def fly = "Flying"
def print(v: Plane & Car): Unit =
println(v.drive)
println(v.fly)
Union (共用体) 型は |
演算子を使用する。次の例に示すように、Union 型の Person | Company
には、Person
のすべての値と Company
のすべての値が含まれる。
def isPersonOrCompany(t: Person|Company) = t match
case p: Person(firstName) => findFirstName(firstName)
case c: Company(registrationNumber) => findRegistrationNumber(registrationNumber)
Scala 3ではいくつかの機能が削除された。たとえば、Symbol
リテラルは、プレーンな String
リテラルか専用のクラスに置き換える必要がある。また、新しい制御構文により、do
キーワードの意味が変わった。do <body> while (<cond>)
の元の構造は、while ({ <body>; <cond> }) ()
に置き換える必要がある。
Scala 3の変更点と新機能の詳細については、ドキュメントをご覧ください。完全な概要は、Scala 3のWebサイトでも入手できる。