Scala3マイグレーションガイドを全て日本語訳にして読んでみた話

## はじめに
この記事は [スタンバイ Advent Calendar 2021](https://qiita.com/advent-calendar/2021/stanby) の13日目の記事です。
昨日の記事は [@nnhiguchi](https://qiita.com/nnhiguchi) さんの [Amazon Rekognitionを使って静止画・動画の節度判定を省力化する](https://qiita.com/nnhiguchi/items/5cbc1ef0bfc08ad08fe7) でした。

#前提
この記事で引用させてもらっているコードは全て[Scala3マイグレーションガイド](https://docs.scala-lang.org/scala3/guides/migration/compatibility-intro.html)のものです。

#ごあいさつ
10月から[株式会社スタンバイ](https://stanby.co.jp/)でSEOエンジニアをやっております、[本田](https://qiita.com/arata-honda)と申します!
スタンバイでは、Scalaを主に使用しています。
自分は今までpython, PHPなどスクリプト言語しか触ったことないので日々勉強の毎日ではありますが、
この度Scalaのキャッチアップもかねて[アドベントカレンダー](https://qiita.com/advent-calendar/2021/stanby)に参加させていただきました！

#和訳して読もうと思ったきっかけ
きっかけは、Scalaの勉強会を漁っていたところ[Reactive System Meetup](https://reactive-shinjuku.connpass.com/event/224070/)を見つけオンライン参加してみたのが初めです。
[Seth Tisue](https://twitter.com/SethTisue)さんが[Scala2からScala3への変換](https://docs.google.com/presentation/d/12IBdH1x_IRk6gcDxWqb7dsAwYkUf66eh5BD3M2LtOw0/edit#slide=id.p)について発表してくださったのを聞いて、
[Scala3マイグレーションガイド](https://docs.scala-lang.org/scala3/guides/migration/compatibility-intro.html)の存在を知りました。
[スタンバイのAPI](https://www.slideshare.net/takezoe/scala-jissenscala-44962449)ではScala2系のフレームワークを使っているので将来Scala3に移行するのかも？ :thinking: と思い、そうなった時にマイグレーションガイドは読んでおいたほうがいいなと思い読み始めました。
日本語は用意されてないので、最初の方は頑張って英語で読んでいたのですが頭に入ってこなく、「これ、日本語訳して読めば、読み込むし内容はいってくるんじゃね？」と脳筋パワースタイルな発想で取り掛かりました。

#どんなことをしたのか
毎朝一時間早く席についてSlackにひたすら和訳していく、それだけです笑

![スクリーンショット 2021-11-25 9.15.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211139/87a7ebee-b733-3a4e-532f-6c9d27b7c9f1.png)

こんな感じで、一日のはじめにScala3のマイグレーションガイドを読むというのが、11/8からはじまり、14日/人で和訳して読むということが終わりました。ここまでやって、「あれ、これOSSコミットできんじゃね？」ってことに気づき、2日かけてSlackにメモ書きしたものを、[Scalaドキュメント](https://github.com/scala/docs.scala-lang)をフォークしてブランチ切り日本語訳を移すという作業をしました。
この段階で意味的に問題ないか読み返しながら移植したので結果的に2回読みました苦笑
おかげで、内容は結構頭にはいってきて結果的にOSSコミットもでき、さらに[スタンバイのアドベントカレンダー](https://qiita.com/advent-calendar/2021/stanby)もかけるという一度で3つ美味しい状態になりました！

#成果物
早速成果物を共有していきたいと思います！
結果的に2つOSSのPRとissueを投げるこができました。1つは和訳したもの、もう1つは和訳する上で、「マークダウンの表の表記おかしくね？」となった軽微な修正、最後はビルドする上でリンク切れになっていたもののissue。
結果的に既存のドキュメントの不備も修正することができてよかったです :smile: 

https://github.com/scala/docs.scala-lang/pull/2235

https://github.com/scala/docs.scala-lang/pull/2236

https://github.com/scala/docs.scala-lang/issues/2244

#やってよかったこと
和訳する上でやってよかったことは、自分はScalaのキャッチアップを[scala-text.github.io](https://scala-text.github.io/scala_text/)でやっていたのですが、その内容を超えるものに関して知ることができたというのが何より良かったです。

- [マクロ](https://docs.scala-lang.org/ja/overviews/macros/overview.html)
- [イータ展開](https://www.scala-lang.org/docu/files/LangSpec2.8-ja_JP.pdf)
- [リフレクション](https://docs.scala-lang.org/ja/overviews/reflection/overview.html)

...

などなど自分の知らなかった言語機能についてキャッチアップできました。
あと前提として、 Scala2.13とScala3の移行について書かれているので、そもそも自分の関わっているプロジェクトがScala2.13以上なのか、とか、sbtのバージョンは1.5.0以上なのか、などアンテナを広げることができたのが良かった点だと思います。

#印象深いページ
ここまで来て内容について触れないのかよ！って言われそうなので、読んでて「何回もこの文書でてきたな」という印象に残ったところを上げていきたいと思います

##Scala 2.13とScala 3はお互いのアーティファクトに依存できる
[クラスパスの互換性のページ](https://docs.scala-lang.org/scala3/guides/migration/compatibility-classpath.html)がまず印象深かったです。なにより、Scala2.13でScala3のオブジェクトをコンパイルして使うことができるんだということに感動しました。

```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")
```
このようにScalaのバージョンを宣言時に指定することでコンパイルできるのはめちゃくちゃビックリしました。
逆にScala2.13をScala3で使う場合は

```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")
```

このように書けばコンパイルすることができます。
[Scalaは全ての値がオブジェクト](https://scala-text.github.io/scala_text/object.html)であるので、これができるのは相当移行が楽になるんじゃないでしょうか？と印象に残りました

##マクロの移行
[マクロの移行ページ](https://docs.scala-lang.org/scala3/guides/migration/tutorial-macro-cross-building.html)も結構繰り返し説明されていて印象に残っています。
Scala3ではScala2のマクロ機能をゼロから作り直しているので、Scala2のマクロを移行する時は書き直ししなければならないということです。
理由としては、Scala 2.13のマクロAPIがScala 2.13コンパイラの内部依存しており、コンパイラ自体も刷新したScala 3コンパイラではScala 2.13マクロを展開することができないからです。
フレームワークとかで内部的につかっているマクロが今後どのように移行していくかは気になるポイントだと思います。

一応マイグレーションガイドにはビルドの方法が2通り記述されていました。
1つはScala2.13とScala3用で二回リリースを行う、[クロスビルド方法](https://docs.scala-lang.org/scala3/guides/migration/tutorial-macro-cross-building.html)で、バージョン固有のソースを専用のディレクトリをつくりそこに再配置してそれぞれコンパイルフェーズで使い分けるというものでした。
2つ目は[ミクシング（合成）](https://docs.scala-lang.org/scala3/guides/migration/tutorial-macro-mixing.html)でScala3のモジュールにScala2.13マクロとScala3のマクロを混ぜるものでした。Scala3コンパイルでScala2のマクロ展開はできないものの定義は読み込むことができるという点を利用しています。最終的に合成したものをScala2.13のアーティファクトに依存させれば使えるよというようなものが例示されいてすごく印象に残っています。

##シンタックスの変更
最後に、[シンタックスの変更ページ](https://docs.scala-lang.org/scala3/guides/migration/tooling-syntax-rewriting.html)も印象に残っていたのでいくつか取り上げてみます。

###手続きシンタックスの型を明示的に示さないといけなくなった: 

```scala
def print() { // Error: Procedure syntax no longer supported; `: Unit =` should be inserted here
    println("bar")
  }
```
これまでは返り値の型を省略しても型推論されていましたが、Scala3では明示的に置かないとエラーになります

```scala
object Bar {
  def print(): Unit = {
    println("bar")
  }
}
```
これに関しては[こちらのScala警察の発表資料](https://www.slideshare.net/takezoe/scala-78377464)にも省略することによるミスリードが説明されていました

###インデントが怒られるようになった：
インデントが今まで自由？にかけてたのが、Scala3ではエラーになるようになりました。
だんだんpythonに近づいている？とすこし思いました :thinking: 

```scala
def bar: (Int, Int) = {
  val foo = 1.0
  val bar = foo // [E050] Type Error: value foo does not take parameters
    (1, 1)
} // [E007] Type Mismatch Error: Found Unit, Required (Int, Int)
```

###型パラメータとしての_が使えなくなった
これまでワイルドカードとしてつかっていた`_`がScala3の型パラメータでは使えなくなっています。

```scala
-- [E040] Syntax Error: src/main/scala/anonymous-type-param.scala:4:10
4 |  def foo[_: Foo]: Unit = ()
  |          ^
  |          an identifier expected, but '_' found
```

結構使っているソースあるのではないでしょうか？
こちらはもう使えなくて明示的に`def foo[T: Foo]: Unit = ???` みたいに記述する必要があります

##ちゃんとリライトオプションを用意してくれているところと全てオプショナルなところ
Scala3のコンパイラオプションでリライトオプションを使うとほぼ網羅的に古いシンタックスを書き換えしてくれるのが驚きです。

>Converting existing Scala code to the new syntax by hand is tedious and error-prone. In this chapter we show how you can use the compiler to rewrite your code automatically from the classic Scala 2 style to the new style, or conversely.
>日本語訳: 既存のScalaコードを手動で新しい構文に変換するのは面倒で、エラーが発生しやすくなります。
この章では、コンパイラを使用して、コードを従来のScala 2スタイルから新しいコードスタイルに、またはその逆について、自動的に書き換える方法を示します。

更に驚きなのは古いシンタックスに切り戻しできるオプションもあるということで、
[シンタックスの書き換えページ](https://docs.scala-lang.org/scala3/guides/migration/tooling-syntax-rewriting.html)でScala3のインデントの書き換えごScala2の記述に戻して一周するというのが記述されていて印象に残りました。
Scala2ユーザのことをちゃんと考慮してくれるなんて本当にScala３の開発者さんは素晴らしいと感動しました。

#最後に
今回和訳することでScalaの言語仕様など、非常に勉強になったので次は[Akka](https://akka-ja-2411-translated.netlify.app/scala.html)などのチュートリアルも読んでいこうかなと思っています!
明日は [＠Nisi](https://qiita.com/Nisi)さんの「【空冷自作PC】Ryzen7 5700G + ASRock DeskMini X300をノクチュア NH-P1でファンレスにした話」です！気になりますね！

# 参考URL
- [株式会社スタンバイ](https://stanby.co.jp/)
- [Reactive System Meetup](https://reactive-shinjuku.connpass.com/event/224070/)
- [Scala3マイグレーションガイド](https://docs.scala-lang.org/scala3/guides/migration/compatibility-intro.html)
- [Making the Transition
to Scala 3 by Seth Tisue](https://docs.google.com/presentation/d/12IBdH1x_IRk6gcDxWqb7dsAwYkUf66eh5BD3M2LtOw0/edit#slide=id.p)
- [Scalaの言語仕様ドキュメント](https://docs.scala-lang.org)
- [Scalaの研修資料](https://scala-text.github.io/scala_text/)
- [Scala警察のすすめ](https://www.slideshare.net/takezoe/scala-78377464)