Scala 再入門 (環境構築)
はじめに
最近新しいことを学んでいなかったので Scala 3 を学んでみようと思う。 Scala という言語は昔は少しばかり流行っていたのだが、最近ではめっきり話を聞かなくなってしまった。単に自分が Scala を使わなくなってしまったのが原因の可能性があるが、昔ほどの勢いは無くなってしまっているように感じる。
Scala 2 を Scala 3 が出る前に少しだけ触っていたので、Scala が流行らない理由はわかる。大体思っていることは以下の記事に書かれているが、Scala を触ろうとする人にとっては当たり前すぎで抜けている視点がいくかあるように感じる。
Scala の難しさをインターネットから集めてみる - Lambda カクテル
私も Scala 自体は好きで C 言語はメモリ管理面倒だし、Java は本質的でない部分の記述が多いし、Kotlin は今でこそサーバサイドでも使われているが、まだ発表されて間もない頃で Android アプリ開発専用言語のような立ち位置で汎用的な目的には使いにくいなぁ、と感じていた頃に関数型プログラミングという当時の私にとって未知のパラダイムは惹かれるものがあった。どういうわけか、関数型プログラミングというパラダイムを当時の私は素直に受け入れることができたが現代においても取っ付き難さは健在だろう。
上述に一点だけ追加で流行らない理由を上げるとすると、コーディングの根底にある immutability (不変性) だ。
え?immutable (不変な) なコードを書いて保守性を上げるのは常識でしょ?
と思ったあなたはモダンな言語や関数型プログラミングに頭をやられてしまっている。現代においてもプログラミング初心者が学ぶ言語は mutable (可変な) データを扱うことが前提だ。最近流行りの Python を始め、Java、JavaScript、C、Go、PHP、Ruby、etc. は値は可変であることを前提にコードが書かれることが多い。もちろん、これらの言語で再代入のないコードを書けないというわけではない。これらの言語は変数が可変であることを良しとしているため、入門サイト、入門書、世の中に存在しているコードは変数の値が変更されることが当然のように行なわれている。
しかし、Scala はどうだろうか?
そのようなコードに慣れ親しんだ人が Scala を触るとどうなるか。
Scala でも var
を使えば再代入はできるけど多くの場面では val
が使われる。つまり、再代入をしないようなコードの書き方をすることが前提となっている。そういったコードを読み慣れていない、書き慣れていない人にとってはこれも最初の障壁となると思う。
昔とは違い ES6 が浸透した現代においては const
を使って再代入をある程度控えるコーディングが普及しているので、初学者の人も再代入をしないことがデフォルトになりつつあるかもしれない。そういう意味では、不変性については私が思っているほど障害にはなっていない可能性はある。
閑話休題。
さっそく Scala 3 を学ぶために環境構築する。
環境構築
昔は sbt
だけ入れればよかったが現在では Coursier というツールを使うのが一般的なようだ。インストール後に cs list
を実行するとわかるが、これらのコマンド管理が行なえるらしい。
1$ cs list2amm3coursier4cs5metals6sbt7sbtn8scala9scala-cli10scalac11scalafmt
Coursier のインストールは Home Manager で管理する。 Home Manager を使っていない人は公式サイトに載っている手順に従ってインストールしよう。
1{ pkgs, ...}:23{4home.packages = with pkgs; [5coursier6];7}
sbt や Scala コンパイラ、Metals も Home Manager で管理できるが、それらについては Coursier で管理する。
Coursier は cs
コマンドとしてインストールされる。最初に sbt
や scala
、scalac
といった基本的なコマンドをインストールするために次のコマンドを実行。
1$ cs setup
これで sbt
がインストールされたが問題がある。
パスが通らない。個人の環境に依るが私の環境では .profile
や .zprofile
を zsh
が認識してくれないので、以下の設定を .zshrc
に追加した。
1case ${OSTYPE} in2darwin*)3export PATH="$PATH:/Users/${USER}/Library/Application Support/Coursier/bin"4;;5*)6# setting for linux7;;8esac
手元の環境の macOS でのみ動作する設定を入れている。 Windows や Linux を使っている人は適宜、設定を修正して欲しい。
晴れて sbt
コマンドが使えるようになったので基本となるプロジェクトを生成する。ミニマムな環境は sbt new scala/scala3.g8
を実行すればよい。
1$ sbt new scala/scala3.g82SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".3SLF4J: Defaulting to no-operation (NOP) logger implementation4SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.5A template to demonstrate a minimal Scala 3 application67name [Scala 3 Project Template]: sample89Template applied in /private/tmp/./sample
これにより Hello, World
と出力するだけのコードを含むフォルダが生成される。
ディレクトリ構造は以下のようになっている。
1tree sample2sample3├── README.md4├── build.sbt5├── project6│ └── build.properties7└── src8├── main9│ └── scala10│ └── Main.scala11└── test12└── scala13└── MySuite.scala14157 directories, 5 files
Main.scala
の中身は以下のような簡単なコード。
1$ cat sample/src/main/scala/Main.scala2───────┬────────────────────────────────────────────3│ File: sample/src/main/scala/Main.scala4───────┼────────────────────────────────────────────51 │ @main def hello(): Unit =62 │ println("Hello world!")73 │ println(msg)84 │95 │ def msg = "I was compiled by Scala 3. :)"10───────┴────────────────────────────────────────────
さっそく実行してみよう。
sample
ディレクトリに移動して sbt run
を実行する。
1$ cd sample2$ sbt run3[info] welcome to sbt 1.10.5 (Azul Systems, Inc. Java 17.0.13)4[info] loading project definition from /private/tmp/sample/project5[info] loading settings for project root from build.sbt ...6[info] set current project to sample (in build file:/private/tmp/sample/)7[info] compiling 1 Scala source to /private/tmp/sample/target/scala-3.5.2/classes ...8[info] running hello9Hello world!10I was compiled by Scala 3. :)11[success] Total time: 1 s, completed 2024/11/17 19:24:17
Hello, World を実行できたし Scala 完全に理解した。
Emacs
開発は Emacs を使って行いたい。 JetBrains に課金しているので IntelliJ を使ってもいいのだが、新しい Mac mini で Emacs の動作が爆速になったので Emacs でいけるところまで試す。
現代において Language Server は不可欠なので Metals をインストールする。 Metals のインストールは公式の手順に従う。
1(setup scala-mode2(:elpaca t))34(setup sbt-mode5(:elpaca t)6(:opt sbt:program-options '("-Dsbt.supershell=false"))7;; WORKAROUND: https://github.com/ensime/emacs-sbt-mode/issues/318;; allows using SPACE when in the minibuffer9(substitute-key-definition10'minibuffer-complete-word11'self-insert-command12minibuffer-local-completion-map))1314(setup lsp-metals15(:elpaca t))1617(setup dap-mode18(:elpaca t)19(:with-mode scala-mode20(:hook dap-mode21dap-ui-mode))22(dap-auto-configure-mode))
lsp-mode
のインストールは省略している。
これで .scala
拡張子のファイルを開くと Metals のインストールを促されるがプロンプトに従ってインストールを進めると Emacs がフリーズする。環境の問題か判断がつかなかったが Coursier で Metals をインストールすることで回避できた。
1$ cs install metals
これにより Scala のソースコードを開いたとき Metals が認識されるのでインストールによるフリーズを回避できる。
型が見れるようになった。
おわり
Scala 3 の環境構築できたし、ブログを書きつつ学習していくぞい。