Skip to content
144 changes: 144 additions & 0 deletions _ja/overviews/scala3-migration/compatibility-classpath.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
---
title: クラスパス互換性
type: section
description: このセクションは、Scala 2.13とScala 3クラスファイルの互換性について説明します。
num: 3
previous-page: compatibility-source
next-page: compatibility-runtime
language: ja
---

コードを書くとき、他のモジュールやライブラリで定義されている公開型やフィールドを使ったり、公開メソッドを呼び出すことができる。
これはコンパイラフェーズの一つである type checker が、公開型、フィールド、メソッドなどのシグネチャを各自を定義するクラスファイルから読み込むことができる限りうまくいく。type checker は、この情報を用いてコード上の意味的一貫性を検査し、これは型検査と呼ばれる。

Scala 2 では、シグネチャは Pickle と呼ばれる独自のフォーマットを用いて保存される。
Scala 3 では少し違っていて、シグネチャ情報だけに留まらずその他の多くの情報を持つ TASTy フォーマットを採用している。
しかし、本題である Scala 2.13 から Scala 3 への移行において役に立つのはシグネチャだけだ。

## Scala 3 Unpickler

はじめの良い知らせとして Scala 3 のコンパイラは Scala 2.13 の Pickle フォーマットを読み込むことができるということ、すなわち、Scala 2.13 によりコンパイルされたモジュールやライブラリに依存したコードの型チェックができるということだ。

Scala 3 の Unpickler は数年間広範囲的にコミュニティビルドによってテストされている。なので使うこと自体は安全だ。

### Scala 3 モジュールは Scala 2.13 アーティファクトに依存できる

![Scala 3 module depending on a Scala 2.13 artifact](/resources/images/scala3-migration/compatibility-3-to-213.svg)

sbt ビルドとして、次のように説明できる( sbt 1.5.0 以降が必要だ):

```scala
lazy val foo = project.in(file("foo"))
.settings(scalaVersion := "3.0.0")
.dependsOn(bar)

lazy val bar = project.in(file("bar"))
.settings(scalaVersion := "2.13.6")
```

または、bar が公開された Scala 2.13 ライブラリである場合は、次のことができる。:

```scala
lazy val foo = project.in(file("foo"))
.settings(
scalaVersion := "3.0.0",
libraryDependencies += ("org.bar" %% "bar" % "1.0.0").cross(CrossVersion.for3Use2_13)
)
```

sbt で `CrossVersion.for3Use2_13` を使用して、`bar_3` の代わりに `bar_2.13` を解決する。

### 標準ライブラリ

Scala 2.13 標準ライブラリは、重要なクロス依存性の例だ。
実は、Scala 2.13 標準ライブラリをそのまま Scala 3 用の公式標準ライブラリとして採用した。

標準ライブラリは自動的にビルドツールにより与えられるため、手動で設定する必要はありません。

## Scala 2.13 の TASTy 読み取り機能

2つ目の良い知らせは、Scala 2.13.4 より Scala 2.13 TASTy 読み取り機能がリリースされ、Scala 2.13 側から Scala 3 で書かれたライブラリ群の呼び出しが可能となったことだ。

> TASTy 読み取り機能はとても新しいものだ。そのため、`-Ytasty-reader` フラグ下でのみ使用できる。

### サポートされている機能

TASTy 読み取り機能は、すべての従来の言語機能に加えて、次の新しい機能をサポートする。:
- [Enumerations]({% link _scala3-reference/enums/enums.md %})
- [Intersection Types]({% link _scala3-reference/new-types/intersection-types.md %})
- [Opaque Type Aliases]({% link _scala3-reference/other-new-features/opaques.md %})
- [Type Lambdas]({% link _scala3-reference/new-types/type-lambdas.md %})
- [Contextual Abstractions]({% link _scala3-reference/contextual.md %}) (new syntax)
- [Open Classes]({% link _scala3-reference/other-new-features/open-classes.md %}) (and inheritance of super traits)
- [Export Clauses]({% link _scala3-reference/other-new-features/export.md %})

限定的にサポートしているもの。:
- [Top-Level Definitions]({% link _scala3-reference/dropped-features/package-objects.md %})
- [Extension Methods]({% link _scala3-reference/contextual/extension-methods.md %})

よりエキゾチックな機能はサポートされていません。:
- [Context Functions]({% link _scala3-reference/contextual/context-functions.md %})
- [Polymorphic Function Types]({% link _scala3-reference/new-types/polymorphic-function-types.md %})
- [Trait Parameters]({% link _scala3-reference/other-new-features/trait-parameters.md %})
- `@static` Annotation
- `@alpha` Annotation
- [Functions and Tuples larger than 22 parameters]({% link _scala3-reference/dropped-features/limit22.md %})
- [Match Types]({% link _scala3-reference/new-types/match-types.md %})
- [Union Types]({% link _scala3-reference/new-types/union-types.md %})
- [Multiversal Equality]({% link _scala3-reference/contextual/multiversal-equality.md %}) (unless explicit)
- [Inline]({% link _scala3-reference/metaprogramming/inline.md %}) (including Scala 3 macros)
- [Kind Polymorphism]({% link _scala3-reference/other-new-features/kind-polymorphism.md %}) (the `scala.AnyKind` upper bound)

### Scala 2.13 モジュールは Scala 3 アーティファクトに依存できる

`-Ytasty-reader` で TASTy 読み取り機能を有効にすることで、Scala 2.13 モジュールは Scala 3 アーティファクトに依存できる。

![Scala 2 module depending on a Scala 3 artifact](/resources/images/scala3-migration/compatibility-213-to-3.svg)

sbt ビルドとして、次のように説明できる。:

```scala
lazy val foo = project.in.file("foo")
.settings(
scalaVersion := "2.13.6",
scalacOptions += "-Ytasty-reader"
)
.dependsOn(bar)

lazy val bar = project.in(file("bar"))
.settings(scalaVersion := "3.0.0")
```

または、`bar` が公開された Scala 3 ライブラリの場合:

```scala
lazy val foo = project.in.file("foo")
.settings(
scalaVersion := "2.13.6",
scalacOptions += "-Ytasty-reader",
libraryDependencies += ("org.bar" %% "bar" % "1.0.0").cross(CrossVersion.for2_13Use3)
)
```

`CrossVersion.for2_13Use3` と同様に、sbt で `CrossVersion.for3Use2_13` を使用して、`bar_2.13` ではなく `bar_3` を解決する。

## 相互運用性の概要

要するに、下位、上位互換性があり、そしてそれにより**移行が段階的に行うことが可能になる**。

ライブラリの依存関係がまだ移植されてない場合(マクロライブラリを除く)でも、一度に Scala アプリケーションの一つのモジュールを移植することができる。

移行期間中、2 つの Scala 2.13 モジュールで挟まれた Scala 3 モジュール層を扱うことができる。

![Sandwich pattern](/resources/images/scala3-migration/compatibility-sandwich.svg)

クロス依存性は、全てのライブラリがそれぞれ単一のバイナリバージョンへと解決される限り許される。例えば、`lib-foo_3` と `lib-bar_2.13` を同じクラスパスに持つことができるが、`lib-foo_3` と `lib-foo_2.13` を含めることはできない。

この逆のパターン、すなわち 2.13 モジュールが中央にある場合でも可能だ。

> #### ライブラリ作者への注意
>
> 公開ライブラリの中で Scala 2.13 と Scala 3 間の相互運用性を使うと、多くの場合そのライブラリを使用するエンドユーザにとって安全では無いことに注意してほしい。
>
> 状況を完全に理解した上級ユーザ以外は、( scala-library 以外の) Scala 2.13 系ライブラリに依存した Scala 3系のライブラリを公開することは非推奨とされており、逆も然りだ。
> なぜなら、ライブラリを使用するユーザを、クラスパス内の同じ foo ライブラリ内の2つのバージョンである `foo_2.13` と `foo_3` の競合から防ぐためであり、この問題は場合によっては解決することができない。
36 changes: 36 additions & 0 deletions _ja/overviews/scala3-migration/compatibility-intro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
title: 互換性リファレンス
type: chapter
description: この章ではScala 2.13とScala 3の互換性について説明しています。
num: 1
previous-page:
next-page: compatibility-source
language: ja
---

Scala 3はScalaエコシステムにおける互換性に関して革新的なものであり、全Scalaプログラマの日々の経験を大きく向上させるでしょう。
互換性の新時代は、Scala 3 マイグレーションから始まる。

Scala 2からScala 3に移ることは大きな急速進歩であります。
Scala 3 は、言語のコアな基礎部分の完全な再設計に基づき構築された新品のコンパイラだ。それでも、Scala 2.12 からScala 2.13 へのときよりも難しくないマイグレーションとなる自信がある。

Scala 2.13 と Scala 3 の間での相互互換性のおかげで、見方によっては以前よりもシンプルになったと言えるかもしれない。

この章では2つのバージョン差異における互換性の詳細について語る。
ここでは、下記に従う疑問についての答えを見つけることができるだろう。:

**[ソース互換性](compatibility-source.html)**
- Scala 3は異なる言語?
- Scala 2.13プロジェクトをScala 3に変換するのはどれくらいハード?

**[クラスパス互換性](compatibility-classpath.html)**
- Scala 3ではScala 2.13のライブラリを使えるのか?
- 逆に、Scala 3のライブラリをScala 2.13で使えるのか?

**[実行時互換性](compatibility-runtime.html)**
- 本番環境においてScala 3プログラムを安全にデプロイできるのか?
- Scala 2.13と比較してScala 3はどれくらいはやいのか?

**[メタプログラミング互換性](compatibility-metaprogramming.html)**
- 所有してるScala 2.13プロジェクトはScala 2のマクロ機能のリプレイスにより影響が出るのか?
- どうすれば、所有するScala 2.13マクロライブラリをScala 3にうつせるのか?
87 changes: 87 additions & 0 deletions _ja/overviews/scala3-migration/compatibility-metaprogramming.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
---
title: メタプログラミング互換性
type: section
description: このセクションはメタプログラミングの移行を解説する。
num: 5
previous-page: compatibility-runtime
next-page: tooling-tour
language: ja
---

マクロメソッドの呼び出しは、マクロ展開と呼ばれるコンパイラフェーズの中で実行され、抽象構文木 (つまりプログラムの一部) を生成する。

Scala 2.13 のマクロ API は Scala 2.13 コンパイラの内部と密接に関連している。
それゆえ、Scala 3 コンパイラでは Scala 2.13 マクロを展開することはできない。

一方 Scala 3 は、安定性を考慮して設計しなおされた、新たなメタプログラミングの方法を導入する。
Scala 3 マクロとそしてそのインラインメソッドは通常、Scala 3 コンパイラの将来のバージョンと互換性がある。
これは異論のない改善だが、新しいメタプログラミング機能を使用して、すべての Scala 2.13 マクロをゼロから書き直す必要があるということも意味している。

## マクロを定義するライブラリ依存性

Scala 3 のモジュールはマクロ定義が含まれている Scala 2.13 アーティファクトに依存することができますが、コンパイラはそれらのマクロを展開することはできないだろう。
マクロ展開に当たると、それは単にエラーが返ってくるようになる。

{% highlight text %}
-- Error: /src/main/scala/example/Example.scala:10:45
10 | val documentFormat = Json.format[Document]
| ^
|Scala 2 macro cannot be used in Scala 3. See https://dotty.epfl.ch/docs/reference/dropped-features/macros.html
|To turn this error into a warning, pass -Xignore-scala2-macros to the compiler
{% endhighlight %}

`-Xignore-scala2-macros` を使うことで型検査の役には立つが、不完全なクラスファイルを生成することに注意してほしい。

あなたのプロジェクトでこのエラーが出た場合、結局の所、マクロ定義元のアーティファクトを Scala 3 系にアップグレードする以外の選択肢は残されていない。

## マクロエコシステムの移行

Scala 2 マクロは実験的機能とは言われつつも、実際の所 Scala コミュニティーは広範囲に渡ってマクロを採用し、コード生成、最適化、使い易い DSL など様々な面で使われている。

大部分のエコシステムは現在 Scala 2.13 マクロにより定義されている外部ライブラリに依存してる。
それらのライブラリの識別や移植はエコシステムを前進させるだろう。

[このページ](https://scalacenter.github.io/scala-3-migration-guide/docs/macros/macro-libraries.html)に多くのオープンソースの移行状態が可視化されている。

## マクロの書き換え

この新しいメタプログラミング機能は完全に Scala 2 と異なる。
構成としては:
- [インラインメソッド][inline]
- [コンパイル時の演算][compiletime]
- [マクロ][macros]
- [クォート][quotes]
- [抽象構文木 (AST) のリフレクション][reflection]

マクロの再実装に深入りしてしまう前に、以下を自問するべきだ:
- `inline` と `scala.compiletime` を使用してロジックの再実装できるだろうか?
- よりシンプルで安全な式ベースのマクロを使うことができるか?
- AST にアクセスすることが本当に必要なことか?
- 返り値の型として[マッチタイプ](/scala3/reference/new-types/match-types.html) を使うことができるだろうか?

新しく登場したメタプログラミングの概念の全ては [Macro Tutorial][scala3-macros] にて解説してある。

## マクロライブラリのクロスビルド

素晴らしいマクロライブラリを書いて、Scala 2.13 系と Scala 3 系の両方でリリースしたいとする。
その場合、従来のクロスビルドと、より新しい mixing macro という 2つの異なるアプローチがある。
詳細は以下のチュートリアルを参考にしてほしい:
- [Cross-Building a Macro Library](tutorial-macro-cross-building.html)
- [Mixing Scala 2.13 and Scala 3 Macros](tutorial-macro-mixing.html)

## 追加のリソース

Blog posts and talks:
- [Macros: The Plan For Scala 3](https://www.scala-lang.org/blog/2018/04/30/in-a-nutshell.html)
- [Scala Days - Metaprogramming in Dotty](https://www.youtube.com/watch?v=ZfDS_gJyPTc)

Early-adopter projects:
- [XML Interpolator](https://github.com/dotty-staging/xml-interpolator/tree/master)
- [Shapeless 3](https://github.com/dotty-staging/shapeless/tree/shapeless-3)

[inline]: {% link _overviews/scala3-macros/tutorial/inline.md %}
[compiletime]: {% link _overviews/scala3-macros/tutorial/compiletime.md %}
[macros]: {% link _overviews/scala3-macros/tutorial/macros.md %}
[quotes]: {% link _overviews/scala3-macros/tutorial/quotes.md %}
[reflection]: {% link _overviews/scala3-macros/tutorial/reflection.md %}
[scala3-macros]: {% link _overviews/scala3-macros/tutorial/index.md %}
29 changes: 29 additions & 0 deletions _ja/overviews/scala3-migration/compatibility-runtime.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
title: 実行時互換性
type: section
description: このセクションではScala 3の実行時の特性について記述しています。
num: 4
previous-page: compatibility-classpath
next-page: compatibility-metaprogramming
language: ja
---

Scala 2.13 と Scala 3 は同じアプリケーションバイナリインターフェイス ( ABI ) を共有する。

> ABI はバイトコード上、または Scala.js IR で Scala コードを表現しているものだ。
> ABI は実行時における Scala プログラムの振る舞いを決める。

Scala 2.13 と Scala 3 の混ざった同一ソースコードをコンパイルすると、非常に似たバイトコードを生成する。
違いとしてはいくつかの機能が変更されたことで、例えば lazy val の初期化が改善した。

ABI の共有により Scala 2.13 と Scala 3 ファイルを同じ JVM クラスでロードできる。
同様に、Scala 2.13 ファイルと Scala 3 `sjsir` ファイルは、Scala.js リンカーによってリンクできる。

予期せぬ実行時の振る舞いをある程度軽減させることができる。
そして、Scala 2.13からScala 3の移行で、実行時のクラッシュとパフォーマンスを安全にしてくれます。

Scala 3 で書かれたプログラムの実行時特性は、一見したところ Scala 2.13系と比較して良くも悪くもなっていない。
しかし、以下の新機能によってプログラムの最適化を行うことができる:
- [Opaque Type Aliases](http://dotty.epfl.ch/docs/reference/other-new-features/opaques.html)
- [Inline Methods](http://dotty.epfl.ch/docs/reference/metaprogramming/inline.html)
- [@threadUnsafe annotation](http://dotty.epfl.ch/docs/reference/other-new-features/threadUnsafe-annotation.html)
29 changes: 29 additions & 0 deletions _ja/overviews/scala3-migration/compatibility-source.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
title: ソース互換性
type: section
description: このセクションでは、Scala 2.13とScala3ソース間の互換性レベルについて説明しています。
num: 2
previous-page: compatibility-intro
next-page: compatibility-classpath
language: ja
---

Scala 3 は、Scala 2 言語の改良版だ。

新構文も追加されたが、Scala 2.13 の言語仕様の大半は今後も有効となる。
しかし、言語機能の一部は単純化されたり、制限されたり、完全に廃止されたものもある。
これらの変更はもっともな理由があり、適切な回避策が可能であるように注意を払って決定された。

一般的に、全ての非互換性に対する簡単なクロスコンパイルソリューションがあり、Scala 2.13からScala 3へ簡単かつスムーズに移行する。
非互換性のコーパスは [非互換性テーブル](incompatibility-table.html)にある。

ただし例外があり、それは従来のScala 2のマクロをリプレイスした新しいメタプログラミングフレームワークだ。
詳細説明に関しては、この章の終わりの[メタプログラミング互換性](compatibility-metaprogramming.html)のセクションにある。

メタプログラミングはさておき、Scala 2.13ソースコードはかなり簡単にScala 3に移植できる。
移行が完了すると、Scala 2には存在しないScala 3の強力な機能を使えるようになるだろう。
全てのScala 2.13ソースコードがコンパイルできるというわけではないというのが欠点だ。
しかしながら驚くことに、新しいScala 3のアーティファクトはScala 2.13の依存関係として使用できる。

詳細に説明するように、下位互換性と上位互換性がある。
これはScala言語の歴史におけるブレイクスルーだ。
Loading