この記事は Kotlin Advent Calendar 2020の11日目の記事です。
普段使わないKotlinの機能について調べてみようと思い、kotlinでscriptを書ける機能について調べてみました。
”scriptを書ける” とは?
Kotlinコードをテキストファイル or 文字列で受け取り、それを実行するという意味になります。
例えば、コマンドライン経由でKotlinコードのファイルを指定して処理を動かしたいときであったり、ユーザが入力したKotlinコードを実行したいケース(IPython/Jupyter notebookのようなイメージ)などが具体的なユースケースになります。
特に前者は、ローカルで動かすちょっとした処理を書きたいけど、shell scriptを書きたくない…とかのケースで有用になります。
メジャーなライブラリ
kscriptというライブラリが、kotlincをWrapして便利に使えるようにしてくれているそうです。
どうやら2016年頃からあるらしいです。
実際に使ってみましたが、かなり手軽に使えました。
インストールは、kscriptのドキュメントに記載されているように、以下コマンドでできます。
curl -s "https://get.sdkman.io" | bash # install sdkman
source "$HOME/.sdkman/bin/sdkman-init.sh" # add sdkman to PATH
sdk install kotlin # install Kotlin
sdk install kscript
以下のように直でKotlinコードを渡して実行することもできるし(初回実行時間が体感3sくらいで、2回目以降が体感0.5sくらいになる)
kscript 'println("hello world")'
以下のようなshell scriptっぽいファイルをファイル名sample.kts
で作成し、kscript sample.kts foo bar
コマンドで実行することもできます。
#!/usr/bin/env kscript
println("Hello from Kotlin!")
for (arg in args) {
println("arg: $arg")
}
※ 実行結果
Hello from Kotlin!
arg: foo
arg: bar
wrapperライブラリなだけあって、以下のような色々な便利機能もあるようです。
- scripts caching: 2回目以降の実行速度が速くなる
- maven dependencies:
@file:DependsOn("com.squareup.okhttp3:okhttp:4.7.2")
といったようにscript内に依存ライブラリを宣言できる。(curlやwgetを使わずにすむ。) - IntelliJ support: 何かしらあるらしい
後述する、公式がサポートしている機能と比較した際の欠点は、kscriptをローカルにinstallする必要がある点です。
公式のサポート状況
Kotlin1.3.70のリリースブログや、Kotlin1.4のリリースノートに、script機能の強化について記載されているため、順調に改善されていっているようです。
先程kscriptの説明で紹介したような使い方であれば、kscriptを使わなくても問題なくできるようで、
以下はコマンドライン経由でKotlinコードを実行する例です。(74
という実行結果が得られます)
kotlin -e "1 + 3 + 70"
また、ファイル経由で実行する場合は、以下のファイルを sample.main.kts
という名前で保存し、kotlinc -script sample.main.kts foo bar
コマンドで実行することができます。
#!/usr/bin/env kotlin
println("Hello from Kotlin!")
for (arg in args) {
println("arg: $arg")
}
こちらも公式サポート機能ということもあり、IntelliJ IDEAによるサポートがありました。
kscriptに比べて機能は少ないけれども、kotlin以外はインストールする必要がない点がメリットのようです。
なおkscriptと違ってartifactの依存関係を探索的に解決してくれないという欠点がいま時点ではあるようなので、もし今自分が選ぶならkscriptを使うだろうと思います。
最後に
kscript、機会があれば使ってみたさ…。
といいつつ、ローカルで簡単にKotlinコードの動かすだけなら、IntelliJ IDEAのscratchファイル機能を使ってできるので、しばらくは使う機会はないかも。