LoginSignup
6
2

More than 3 years have passed since last update.

babashkaで使えるClojure機能は限定的

Posted at

前置き

初回起動が遅いためprint文すら1秒かかるClojureで JVMにオプション指定するんだ とか GraalVMに入門するんだ とか様々な工夫が試みられている中に颯爽と現れたbabashkaは初回起動が普通に早い。頻繁に起動させる使い方でも耐えられそう。

じゃあもう全部babashkaでいいじゃんと思ったら 機能に制限があるらしい (Clojureの全ての機能は使えない)

たとえば babashka-sampleプロジェクトをこんな感じで1ファイルにまとめる時、もし利用できない機能が含まれているとエラーが出る (本稿ではそういう話をする)

$ bb -cp $(clojure -Spath):classes -m babashka-sample.main --uberscript standalone.clj

※ 元々babashkaは bashスクリプトで行わせる処理をClojureで書いてしまおうという発想らしいので、babashkaで何でもやろうとする考えはbashで何でもやろうとする考えに近いのかもしれない。。。

The main idea behind babashka is to leverage Clojure in places where you would be using bash otherwise.

clojure.specを使うためspartan.specがある

clojure.spec.alphaをrequireするClojureプログラムは、babashkaで使おうとするとシンボル解決のエラーになる模様。
clojure 1.10.1で試した。

$ bb -cp $(clojure -Spath):classes -m babashka-sample.main --uberscript standalone.clj

clojure.lang.ExceptionInfo: Could not resolve symbol: c/symbol [at clojure/spec/gen/alpha.clj, line 22, column 17]

clojure 1.10.2-alpha1使えば?という言及があるので試したが、ダメみたい (バージョンで解決するのか……)

$ bb -cp $(clojure -Spath):classes -m babashka-sample.main --uberscript standalone.clj

clojure.lang.ExceptionInfo: Could not resolve symbol: c/delay [at clojure/spec/gen/alpha.clj, line 43, column 7]

https://github.com/borkdude/spartan.spec を使えば良いらしい、とは書いてあった。

たぶん動くが、 fdef (関数に対するspec)が未対応らしい :innocent:
clojure.specのことをfdefが全てみたいに思っていた節があるので悲しい

なお、自分のプロジェクトはspartan.specで代替できたとしても、外部ライブラリで clojure.spec.alphaを活用しているものがあると、読み込み時に弾かれて使えない。
specを使う integrantが弾かれ、integrantを使う duct.coreが弾かれ、これもうわかんねえな。

多分Javaクラスの多くが未対応

Javaクラスの多くをシンボル解決できない疑惑がある。

System/getenvは使えるし、babashkaのゴールとしても一般的なライブラリを使用可能にするらしいとは書かれている

clj-http

clj-httpを読み込んだ時に org.apache.commons.codec.binary.Base64 (java.lang.Class)がシンボル解決エラーで弾かれた。

clj-httpを利用するライブラリ……たとえば clj-slackも当然読み込めない。

(httpライブラリを使いたければ borkdude/clj-http-liteを使う必要がありそう)

Protocol

babashka v0.1.1から (defprotocol)が使えるらしい。
cf. https://github.com/borkdude/babashka/blob/master/CHANGELOG.md#v020-2020-08-28

が、その Protocol機能を使っている時も、第一引数の型をJavaクラス表記で書くとダメみたい。

たとえばこうやってrecord MyTypeをただ指定して、

(defrecord MyType [element])

(defprotocol MyProtocol
  (sample [type]))

(extend-protocol MyProtocol
  MyType
  (sample [type]
    (println "プロトコルを実行したぞい")
    nil))

(sample (->MyType 5))とかで呼ぶプログラムは大丈夫だが、

(extend-protocol)で受け取る第一引数の型を、

(extend-protocol MyProtocol
  babashka_sample.main.MyType
  (sample [type]
    (println "プロトコルを実行したぞい")
    nil))

のようにJavaクラス表記 babashka_sample.main.MyTypeで書くとシンボル解決エラーになる。

$ bb -cp $(clojure -Spath):classes -m babashka-sample.main --uberscript standalone.clj

clojure.lang.ExceptionInfo: Could not resolve symbol: babashka_sample.main.MyType [at /home/v2okimochi/dev/babashka-sample/src/babashka_sample/main.clj, line 16, column 3]

どちらの例でも (->MyType)の型を見るとjavaクラスらしいので、何が違うのかはよくわかっていない。

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2