Scala CLI 1.8.1がしばらく前にリリースされていた。このリリースの主な変更は、using fileディレクティブで URL を展開する機能が利用できるようになったことだ。
この記事ではこの機能について紹介する。
Scala CLI とは
Scala CLI とはVirtusLab社によってメンテナンスされている、事実上標準の Scala 用 コマンドラインツールだ。
この記事でも何度も取り上げており、Scala によるスクリプティングやパッケージ作成などをスムーズに行うことができる非常に便利なツールだ。
Scala CLIでは、.scala.scという拡張子でScalaコードを書くと、それを上から下へとそのまま実行してくれる:
// code.scala.sc println("Hello, Scala CLI!")
% scala-cli code.scala.sc (ファイルをそのまま渡すと scala-cli run ファイル したとみなされる) Hello, Scala CLI! %
ディレクティブとは
単一のScalaコードでできることは限られている。普通はビルドツールの助けを借りて、複数ファイルの結合や依存するライブラリの用意、コンパイラのバージョンの固定、コンパイルオプションの設定をやってもらっているのに、それができないからだ。
Scala CLI では、こうした「スクリプティングのために、ただコンパイルする以外にも必要なこと」をやってくれるための仕組みが用意されている。それがディレクティブ(directive)だ。
ディレクティブはファイルの先頭に//>という特殊なコメントの形式で書き込む:
//> using scala 3.7.1 //> using dep com.lihaoyi::os-lib:0.9.1 println("このスクリプトはかならずScala 3.7.1 コンパイラで処理される") println(os.pwd) // ライブラリのメソッドを利用できる
特別な設定ファイルを用意せずにファイルのコメントで解決するという優れた仕組みによって、ファイル単体で非常に優れた移植性を発揮できるのが Scala CLI の優れた特長だ。
主なディレクティブとして以下のようなものがよく使われる:
using scala: Scala のバージョンを固定するusing dep: 外部ライブラリの利用を宣言する- Scala CLIが勝手にライブラリを用意してくれるので他にすることはない
using javaOpt:JAVA_OPTSを指定するusing option: Scala のコンパイラオプションを指定するusing platform: コンパイルターゲットを指定するusing platform jsとすれば Scala.js でコンパイルされる
利用可能なディレクティブの全ては、以下のページで一覧できる:
file ディレクティブ
そして、Scala CLI はusing fileというディレクティブを用意している。このディレクティブを利用すると、他のファイルをインクルードして実行できる:
//> using file another.scala // ここでは another.scala に定義されたメソッドなどを呼べる
file ディレクティブに URL を指定する
さて、Scala CLI 1.8.1 では file ディレクティブにURLを指定する機能が追加された。つまり、これまではローカルなパスを指定していたところに、外部のURLを書くことで、自動的に Scala CLI にそのファイルをフェッチさせてコンパイルさせられるようになったということだ。
//> using scala 3.7.1 //> using file https://gist.github.com/windymelt/8814833b1e788874b3b9a7a1418abf1a/raw/f9812204a64785af4159c790293d2df09c805e54/library.scala println(dev.capslock.gist.scalacli.Greeting.hello("Windymelt"))
このコードは以下の Gist を参照している:
実行すると自動的に Gist のコードがフェッチされ、実行される:
% scala-cli run.scala.sc Hello, Windymelt!
感想
URL を直接指定できるようになったことで、リリースが大変面倒な Maven Central を経由せずにアーティファクトを利用できるようになった。ただし、Maven Central にアップロードされた Scala のライブラリはあらかじめビルドされてバイトコードになっているのに対して、using fileを利用する方法は単に Scala コードをコンパイルするので、コンパイル分の手間がかかる(ビルド結果はキャッシュされる)ことに注意が必要だ。
また、今のところフェッチしてきたファイルの integrity を検証するための仕組みがないので、ドメインが奪取されるなどした場合に任意のコード実行が許されるという潜在的な危険性をはらんでいることに注意が必要だ。
個人的にも気になったのでGitHubに起票してみた。