Scala
Dotty
ScalaDay 15

WindowsでもDotty

この記事はScala Advent Calendar 2017の15日目の記事になります。

概要

Scala次期バージョンとして順調にリリースが続いているDotty
今のうちに少し触ってみようと思い立ったものの、Windowsに対する公式サイトのサポートはあまり親切ではありません…。パッケージマネージャはhomebrewしか対応しておらず、zipをダウンロードしてみれば各種コマンドはbashで提供されているのみ。

というわけで、Windowsでお手軽にDottyを試してみるための方法をまとめました。

前提

SBTがインストール済みでパスが通っているものとします。
Scalaを使用していれば自ずと満たしている条件かと思います。
SBTのバージョンは0.13系を使用しましたが、1.0系でも問題ないと思われます。

Hello world

コマンドプロンプトで下記を実行します。

cmd.exe
sbt new lampepfl/dotty.g8

プロジェクト名を聞かれるので入力すると、現在のフォルダ配下にプロジェクトが作成されます。
プロジェクトのフォルダに移動し、下記を実行。

cmd.exe
sbt run

テンプレートプロジェクトの実行結果が表示されたと思います。めでたしめでたし。
sbtがDotty環境をお膳立てしてくれるので、別途インストールしたりする必要はないのでした。

IDE

実行環境は整ったものの、静的型付け言語はIDEを使ってナンボ。
公式に推奨されているVisual Studio Codeに加え、IntelliJ IDEAでの対応方法を確認してみます。

Visual Studio Code

Visual Studio Codeをダウンロードしてインストール。
インストール時の設定は特に弄らなくても良さそうです。

インストール後、コマンドプロンプトで先ほど作成したプロジェクトのフォルダに移動し、下記コマンドを実行します。

cmd.exe
sbt launchIDE

Visual Studio Codeで該当プロジェクトを開きつつ、Visual Studio Codeで必要なプラグインのインストールまでやってくれます。

IntelliJ IDEA

WindowsでScalaを触っていればおそらくお世話になっているであろうIntelliJ IDEA。
調べてみると、LSP SupportというLanguage Server Protocol用のプラグインが存在しました。早速インストールして設定を行います。

設定はメニューのFile -> Settings -> Languages&Frameworks -> Language Server Protocolにあります。
Server Definitionsに下記を設定すればOKです。

Extension
scala
Artifact
ch.epfl.lamp:dotty-language-server_0.5:0.5.0-RC1
Main class
dotty.tools.languageserver.Main
Args
-stdio

上記設定に加え、scalaプラグインと処理が競合するのでscalaプラグインを無効にしておく必要があります。
IDEAの再起動後に設定が有効になります。
再起動後、ステータスバー右端に緑の丸が表示されていればOKです。
先のプロジェクトを開き、Main.classを表示すると、宣言へのジャンプやオートコンプリートが動作していることが確認できます。
ただし、自分の環境では頻繁にタイムアウトが発生しました。
また、コードの色分けができなかったりオートコンプリート等も若干残念な感じだったり、色々なところで難があります。
scalaプラグインと共存できないのが痛いので、しばらくは様子見となりそうです。

Dottyを試す

テンプレートのMain.scalaだとDottyならではのコードが何一つ存在しないため、下記のように編集してみます。

Main.scala
object Main {
  case class User(name: String)

  case class Group(name: String, users: Seq[User])

  val users: Seq[User] = Seq(
    User("user1"),
    User("user2"),
    User("user3")
  )

  val groups: Seq[Group] = Seq(
    Group("group1", Seq(users(0))),
    Group("group2", Seq(users(1), users(2)))
  )

  def search(name: String): Option[User | Group] = {
    val user = users.find(_.name == name)
    val group = groups.find(_.name == name)
    user orElse group
  }

  def main(args: Array[String]): Unit = {
    println(search("user2"))
    println(search("group2"))
    println(search("group5"))
  }
}

Union typesを試してみました。もうちょっといい例はないものかと思いますが…。
実行結果は以下のようになります。

実行結果
Some(User(user2))
Some(Group(group2,List(User(user2), User(user3))))
None

終わりに

言語仕様としては魅力的なDottyですが、Visual Studio Codeを使用してもIDEサポートはまだまだのように感じられました。
IntelliJ IDEAのScalaサポートが手厚いため、相対的にそう感じられるだけかもしれませんが…。
正式版がリリースされる頃にはこのあたりの問題も解決しているといいなあ、と思います。