🥛

Scala.js始めるのでチュートリアルのメモ

2021/07/04に公開

どうも@armorik83 です。

周りを見渡すと、ちょうど Elixir やってる人や Rust 始めちゃってる人が居たので、自分もなんかやるかーと思って、Scala に手を出そうかな。せっかく Scala.js なんていう最高にロックな AltJS(?)があるので、まずはそこを足掛かりにしていく。

ちなみに日本だけだろうが、Scala.jsググると公式を押しのけてトップに現れるブログがある。イカでいう「もうここも塗られてた」状態である。さすがだ。

Scala.js チュートリアル

http://www.scala-js.org/doc/tutorial.html

今回はこのチュートリアルに従っていく。以下の内容は執筆時点のものなので、基本的には上記チュートリアルの最新のコード・コマンドを参照されたい。

sbt インストール

http://www.scala-sbt.org/download.html

brew install sbt

brew があるならそれで。ちなみに sbt は"Scala-oriented build tool"の略だそうです

新規プロジェクト用のディレクトリを作成

scalajs-tutorial内で作業する。

mkdir ~/Desktop/scalajs-tutorial && cd $_

プラグインの使用宣言

./project/plugins.sbtを作成する。

mkdir project
echo 'addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.6")' > project/plugins.sbt

build.sbt

build.sbtを作成する。

touch build.sbt
enablePlugins(ScalaJSPlugin)
name := "Scala.js Tutorial"
scalaVersion := "2.11.7" // or any other Scala version >= 2.10.2

※ 後述するが、ここはその時々の Scala のバージョンと一致しないとエラーが出る。

./project/build.propertiesが必要らしいので作る。

echo 'sbt.version=0.13.9' > project/build.properties

TutorialApp.scala を作成

いよいよ Scala ファイルを作成する。随分と深いところに作らされるが、おとなしく従う。なお、この時点で Scala の文法等詳細は全然学んでいない。コピペです。

mkdir -p src/main/scala/tutorial/webapp/; touch src/main/scala/tutorial/webapp/TutorialApp.scala
TutorialApp.scala
package tutorial.webapp

import scala.scalajs.js.JSApp

object TutorialApp extends JSApp {
  def main(): Unit = {
    println("Hello world!")
  }
}

sbt run

JDK が必要

起動すると早速怒られた。(JDK が入っている方は読み飛ばして OK)

sbt

No java installations was detected.
Please go to http://www.java.com/getjava/ and download

('・c_・` )ソッカー

ここで表示されるhttp://www.java.com/getjava/は罠なので、ここに行ってもしょうがない、JDK が必要。

http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

ここから"Mac OS X x64"を選択しダウンロード。インストールはJDK 8 Update 45.pkgに任せる。終わったら確認。

/usr/libexec/java_home -V

Matching Java Virtual Machines (1):
    1.8.0_45, x86_64:	"Java SE 8"	/Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home

/Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home

sbt 起動

気を取り直して、もう一度。

sbt

Getting org.scala-sbt sbt 0.13.7 ...
downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/sbt/0.13.7/jars/sbt.jar ...
	[SUCCESSFUL ] org.scala-sbt#sbt;0.13.7!sbt.jar (3829ms)
downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/main/0.13.7/jars/main.jar ...
	[SUCCESSFUL ] org.scala-sbt#main;0.13.7!main.jar (6380ms)

行けたみたいだ。ここから色々落としていてかなり時間がかかるので、根気強く待つ:coffee:

[info] Done updating.
[info] Set current project to Scala.js Tutorial (in build file:/Users/armorik83/Desktop/scalajs-tutorial/)
>

終わったらこんな感じにプロンプトが立ち上がるので、runする。

sbt
run

maven が動いているらしく、またかなり待つ。

エラーの対処

案の定こういうのは一発でいかない。

sbt
[warn] Scala version was updated by one of library dependencies:
[warn] 	* org.scala-lang:scala-library:2.11.5 -> 2.11.7
[warn] To force scalaVersion, add the following:
[warn] 	ivyScala := ivyScala.value map { _.copy(overrideScalaVersion = true) }
[warn] Run 'evicted' to see detailed eviction warnings
[warn] No main class detected
[trace] Stack trace suppressed: run last compile:scalaJSLauncher for the full output.
[error] (compile:scalaJSLauncher) No main class detected.
[error] Total time: 0 s, completed Jul 4, 2015 9:55:23 PM

ひとまずbuild.sbtの記述をscalaVersion := "2.11.7"に改めて再度実行した。一旦 sbt 内でexitしてから再度 sbt を起動しないと反映しないので注意。そしてまたえらい待つ。

sbt
> run
[warn] No main class detected
[trace] Stack trace suppressed: run last compile:scalaJSLauncher for the full output.
[error] (compile:scalaJSLauncher) No main class detected.
[error] Total time: 0 s, completed Jul 4, 2015 10:00:30 PM

また同じエラーだ。No main class detected、そんなバカなと思ったらTutorialApp.scalaが 0 bytes のままで、バカなのは自分だった:joy_cat: リアルタイムに作業しながらこの記事を書いているので、もうこのまま進める。

コンパイル成功

正しく実行されると次のように表示される。

sbt
> run
[info] Compiling 1 Scala source to /Users/armorik83/Desktop/scalajs-tutorial/target/scala-2.11/classes...
[info] Running tutorial.webapp.TutorialApp
Hello world!
[success] Total time: 1 s, completed Jul 4, 2015 10:01:17 PM

なんとか行けた。

Run with Node.js (fastOptJS)

Scala.js では"Run with Node.js"という run の手法があるようで、これは公式のチュートリアルで推奨されている。

sbt
$ sbt fastOptJS
[info] Loading project definition from /Users/armorik83/Desktop/scalajs-tutorial/project
[info] Set current project to Scala.js Tutorial (in build file:/Users/armorik83/Desktop/scalajs-tutorial/)
[info] Fast optimizing /Users/armorik83/Desktop/scalajs-tutorial/target/scala-2.11/scala-js-tutorial-fastopt.js
[success] Total time: 1 s, completed Jan 30, 2016 2:09:11 PM

おー、たしかに速い。で、この時コンパイルされた.jsはどこかというと./target/scala-2.11/scala-js-tutorial-fastopt.jsだ。

fullOptJS

sbt fullOptJS

というコマンドで、いちいち sbt を起動させずにいきなり sh で打つこともできる。コンパイルは上記の Scala ソースで 2 秒。かつては分単位で掛かっていたそうなので、十分現実的な速さだろう。(それでも増えてくると遅いとの噂)

あとこの出力された JS ソースは、Lint の効いた Atom で開いたら最新の Mac でさえ 1 分ほど固まったので、Lint 有効のまま開かない方がいい。

JSFiddle で確認してみて

最後に実際に動く例を貼っておく。使った Scala ソースは以下。

HelloWorld.scala
package example

import scala.scalajs.js

object HelloWorld extends js.JSApp {
  def main(): Unit = {
    println("Hello world!")
  }
}

https://jsfiddle.net/qucn4ka4/

一番下に小さく書かれたexample.HelloWorld().main();が呼び出し側だ。まあ、なんというか、すごいな。

おわりに

なるほど、これが今ちまたで大流行中のAltJS か!

まだ Hello world!しかできていませんが、JS 界と Scala 界をつなぐjs.JSAppを学べて、ちょうど今作りたいネタもあるので、しばらく遊んでみます。

ちなみに 1 年半ほど前に AltJS (TypeScript)に手出しした直後は、私はこんな記事をぬかしていました。思えば遠くに来たもんだ。

以上です。

参考リンク

Discussion