たにしきんぐダム

プログラミングやったりゲームしてます

Scripting with Scala CLI

Scala Advent Calendar 8日目の記事です。

Scalaスクリプト書いてますか?僕は書いてません、でした、最近までは。

隣のクラスのPythonやGoはインタープリタコンパイラをインストールしたらすぐに適当なスクリプト書き始められるというのに、Scalaときたらちょっとしたスクリプト書くのにもsbtなりのビルドシステムをセットアップして〜みたいなことしないといけない。

そんなあなたにはこれ!

scala-cli.virtuslab.org

Scala CLIScala をサクッと書くための CLI ツールで、これさえインストールすればsbtなどのビルドツールを使わなくてもすぐに一通りのプログラムを書くことができるようになります。

インストール方法とかはドキュメントを見てもらって、Scala CLI 使ってなにか書いてみましょう。

scala-cli.virtuslab.org

ここ最近の為替レートのチャートを表示するスクリプト書いてみる

最近は円安すごくて為替レート気になりますよね。ということでCLIからサクッと為替レート見れるスクリプトを書いてみます。(とりあえずEUR->JPYで)

為替レートの取得には Exchange Rates API を使って、ライブラリは以下のものを使います。

できました。(secret に取得したAPIトークンを入れてね)

#!/usr/bin/env -S scala-cli shebang --quiet

//> using lib "com.softwaremill.sttp.client3::core:3.8.3"
//> using lib "com.mitchtalmadge:ascii-data:1.4.0"
//> using lib "com.lihaoyi::ujson:2.0.0"
import ujson._
import sttp.client3._
import com.mitchtalmadge.asciidata.graph.ASCIIGraph

import java.time._

val secret = "xxx"

val endDate = if (args.length > 1) LocalDate.parse(args(1)) else LocalDate.now()
val startDate = endDate.minus(Period.ofDays(90))
val client = SimpleHttpClient()
val response = client
  .send(
    basicRequest
      .header("apikey", secret)
      .get(
        uri"https://api.apilayer.com/exchangerates_data/timeseries?start_date=${startDate}&end_date=${endDate}&base=EUR&symbols=JPY"
      )
  )
val responseBody =
  response.body.getOrElse(throw new Exception("Service not responding"))
val data = ujson.read(responseBody)
val values =
  data("rates").obj.toSeq.sortBy(_._1).map((_, value) => value("JPY").num)
println(ASCIIGraph.fromSeries(values.toArray).plot())

これを script.sc として保存して以下のコマンドで実行。

$ scala-cli script.sc
# もしくは
$ chmod +x script.sc
$ ./script.sc

実行すると直近90日のEUR->JPYの為替レートが以下のような感じのascii chartで表示されます。

実行結果(うまくコピペできなかった)

解説

using lib なんちゃらって何?

//> using lib "com.softwaremill.sttp.client3::core:3.8.3"

using directive っていうやつ。//> using lib "org::name:version" でそのスクリプトからライブラリをダウンロードして使えるようにしてくれる。(裏側ではcoursierを使ってダウンロードされてivyキャッシュに保存されるので、実行するたびにダウンロードされることはないよ)。

scala-cli.virtuslab.org

どのバージョンのScalaが使われてるの?

デフォルトだと最新(今だと3.2.0)。

$ scala-cli -S 2.13.10 script.sc みたいな感じで Scala のバージョンを指定したり

//> using scala "2.13.10"sc ファイルの頭につけて、using directive でバージョン指定もできる。

IDE サポートは?

あります! Metals の場合は .sc ファイルを開くと、scファイルが見つかりました、ScalaCLI script としてインポートしますか? みたいなのが出るのでハイを押すと普通にIDE機能を使った状態でスクリプトを書くことができるようになる。

もしくは IDE Setup | Scala CLI

ammonite とは何が違うの?

裏側では ammonite 使ってます(それにいろいろ便利機能をラップした感じ)。なので ammonite でできることはだいたいできるはず。

ammonite でできること。

blog.3qe.us

なんで ./script.sc で実行できるの?

shebang#!/usr/bin/env -S scala-cli shebang って書いてるから。

https://scala-cli.virtuslab.org/docs/guides/scripts#self-executable-scala-script


これで Scala でもシュシュッとスクリプト書けるぞ!!!

良いブログ

alexn.org

ちなみに

(ちなみに今後 scala コマンドをこの scala-cli で置き換えるという SIP が提案され、最近 accept されました)。

contributors.scala-lang.org

contributors.scala-lang.org