Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

Scala 3 勉強会#1 ことはじめ

Scala 3 勉強会#1 ことはじめ

社内で Scala 3 勉強会を実施した際の資料(公開用)。

目次
・Scala 3 コンパイラのインストール
・TASTy について
・Scala 3 の制御構文

Tomoki Mizogami

August 27, 2021
Tweet

More Decks by Tomoki Mizogami

Other Decks in Programming

Transcript

  1. 第0回の振り返り • Scala 3 マイグレーションガイド ◦ Scala 2.13 から Scala

    3 への移行は基本的にはカンタン。ただし ▪ コンパイラプラグイン、マクロ等を使っている場合はコードの更新も必要 😢 ▪ 例)Slick, Twirl, play-json, scala-reflect etc. ◦ Scala 2.13.6 ⇄ Scala 3 間で、クラスパスレベルでの互換性あり ▪ TASTy Reader • Hamcat の Scala 3 対応 ◦ 依存ライブラリを Scala 3 対応版にアップグレードすれば良い ◦ Scala 3 対応がどれだけ複雑になるかは、 依存ライブラリ+コンパイラプラグイン に依る
  2. 前回出た疑問 • Play Framework (Scala 2.13) を Scala 3 で利用できるのではないか?

    ◦ Play Framework の sbt プラグインには Twirl が含まれているため、単純にはできなさそう ◦ libraryDependencies += ("com.typesafe.play" %% "play" % “2.8.8”).cross(CrossVersion.for3Use2_13) とかにして、HTTP サーバーから作ればいけ るか・・・? ◦ Play Framework に関しては、Akka と Twirl、play-json が Scala 3 対応するまでアプデ しない方がよさそう
  3. Scala 3 インストール • ガイド [1] に従う $ brew update

    # Coursier インストール $ brew install coursier/formulas/coursier && cs setup #コンパイラ、REPL インストール $ cs install scala3-compiler $ cs install scala3-repl # REPL 起動してみよう $ cs launch scala3-repl scala> for i <- (1 to 10) do println(s"Hello $i") Hello 1 Hello 2 Hello 3 Hello 4 Hello 5 Hello 6 Hello 7 Hello 8 Hello 9 Hello 10
  4. Scala 3 インストール • 以下のコードをコンパイルしてみよう (Hello.scala) $ vim Hello.scala @main

    def hello = println("Hello, world") :wq $ cs launch scala3-compiler -- Hello.scala $ ls -l Hello$package$.class Hello$package.class Hello$package.tasty Hello.scala hello.class hello.tasty
  5. TASTy: Typed Abstract Syntax Trees • TASTy = 型付き抽象構文木 ◦

    プログラムの文法構造、型等の完全な情報を持つ • .tasty ファイルは、TASTy をファイルにしたもの • An Overview of TASTy [2]
  6. TASTy: なぜ必要なのか • Scala 2 コンパイラは .class ファイルを生成する • .class

    ファイルを生成する段階で、型情報が削減されることがある • 例 [2, 5] $ vim TypeErasure.scala val xs: List[Int] = List(1, 2, 3) val x = xs(0) :wq $ cs launch scala3-compiler -- TypeErasure.scala $ javap TypeErasure\$package\$ Compiled from "TypeErasure.scala" public final class TypeErasure$package$ implements java.io.Serializable { public static final TypeErasure$package$ MODULE$; public static {}; public scala.collection.immutable.List<java.lang.Object> xs(); public int x(); }
  7. TASTy: なぜ必要なのか • Scala 2 コンパイラは .class ファイルを生成する • .class

    ファイルを生成する段階で、型情報が削減されることがある $ vim TypeErasure.scala val xs: List[Int] = List(1, 2, 3) val x = xs(0) :wq $ cs launch scala3-compiler -- TypeErasure.scala $ javap TypeErasure\$package\$ Compiled from "TypeErasure.scala" public final class TypeErasure$package$ implements java.io.Serializable { public static final TypeErasure$package$ MODULE$; public static {}; public scala.collection.immutable.List<java.lang.Object> xs(); public int x(); } List[Int] → List<Object> になっている x: Int を取得するときはキャストされている Scala 3 の Union Type とかも無くなる
  8. TASTy: メリット [2, 6] • .tasty ファイルを通して、Scala 2.13.6 から Scala

    3 のコードを利用できる (TASTy Reader) • 分割コンパイルをサポートできるらしい • LSP (Language Server Protocol) で利用できるらしい • マクロの生成方法に関係しているらしい • コード最適化ツール、解析ツールに利用できるらしい
  9. 文法 (1): if 式 [7, 8] • then があれば、条件式にカッコが必要なくなった def

    ifFunc1(x: Int) = if (x < 0) { "negative" } else if (x == 0) { "zero" } else { "positive" } def ifFunc1(x: Int) = if x < 0 then "negative" else if x == 0 then "zero" else "positive" Scala 2 Scala 3
  10. 文法 (1): for 式 • yield か do をつければ、enumerator にカッコが必要なくなった

    • for ループを表す、do が追加 def forFunc1(xs: Seq[Int]) = for (x <- xs if x > 0) yield x*x def forFunc2(xs: Seq[Int], ys: Seq[Int]) = for { x <- xs y <- ys } yield println(x + y) def forFunc1(xs: Seq[Int]) = for x <- xs if x > 0 yield x * x def forFunc2(xs: Seq[Int], ys: Seq[Int]) = for x <- xs y <- ys do println(x + y) Scala 2 Scala 3
  11. 文法 (1): while 式 • do があれば、条件式にカッコが必要なくなった def whileFunc1(x: Int,

    f: Int => Int) = { var tmp = x while (tmp >= 0) { println(tmp) tmp = f(tmp) } } def whileFunc1(x: Int, f: Int => Int) = var tmp = x while tmp >= 0 do println(tmp) tmp = f(tmp) Scala 2 Scala 3
  12. 文法 (1): try 式 • 1つの case であれば、1行で書けるようになった try throw

    new IOException catch case ex: IOException => println("error") Scala 2 Scala 3 try { throw new java.io.IOException } catch { case ex: java.io.IOException => println("error") }
  13. まとめ • Scala 3 コンパイラは、.class ファイルだけでなく .tasty ファイルも生成する • .tasty

    は、プログラムの完全な情報を持つ TASTy を表現する • TASTy-Reader 経由で、Scala 2.13.6 のコードは Scala 3 のコードを読み 込める • プログラムをシンプルにするような工夫が文法に追加された
  14. 次回予告 • 引き続き、New in Scala 3 を上から読んでいく ◦ new キーワードについて

    ◦ Scala 3 から追加されたインデント規則について ◦ ワイルドカード型が _ から ? になったことについて • その他コンテンツ、ご自由にどうぞ ◦ Scala 3 対応済みのライブラリで、 HTTP サーバーや DB レイヤーを実装してみよう ▪ HTTP: zio-http, http4s, akka ▪ DB レイヤー: ScalikeJDBC, Doobie (新しく追加されたデータ型も早くやりたいかもですが、まずは文法からご紹介していこうかと!)
  15. [1] Getting Started with Scala 3, https://docs.scala-lang.org/ja/scala3/getting-started.html [2] An Overview

    of TASTy, https://docs.scala-lang.org/scala3/guides/tasty-overview.html [3] Dotty, https://github.com/lampepfl/dotty/tree/master/tasty-inspector/src/scala/tasty/inspector [4] scala3-tasty-inspector.g8, https://github.com/scala/scala3-tasty-inspector.g8 [5] javapコマンドでクラスファイルを読む, https://atmarkit.itmedia.co.jp/ait/articles/0407/13/news102.html [6] Macros: the Plan for Scala 3, https://www.scala-lang.org/blog/2018/04/30/in-a-nutshell.html [7] New in Scala 3, https://docs.scala-lang.org/ja/scala3/new-in-scala3.html [8] New Control Syntax, https://docs.scala-lang.org/scala3/reference/other-new-features/control-syntax.html 参考リンク