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

# 前置き
初回起動が遅いためprint文すら1秒かかるClojureで [JVMにオプション指定するんだ](https://tnoda-clojure.tumblr.com/post/51495039433/jvm-%E3%81%AE%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3%E8%A8%AD%E5%AE%9A%E3%81%A7-clojure-%E3%81%AE%E8%B5%B7%E5%8B%95%E3%82%92-30-%E9%AB%98%E9%80%9F%E5%8C%96) とか [GraalVMに入門するんだ](https://tech.uzabase.com/entry/2020/01/27/090000) とか様々な工夫が試みられている中に颯爽と現れた[babashka](https://github.com/borkdude/babashka)は初回起動が普通に早い。頻繁に起動させる使い方でも耐えられそう。

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


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

```bash
$ 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で試した。

```bash
$ 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使えば？](https://github.com/borkdude/babashka/issues/125#issuecomment-644865116)という言及があるので試したが、ダメみたい (バージョンで解決するのか……)

```bash
$ 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](https://github.com/weavejester/integrant)が弾かれ、integrantを使う [duct.core](https://github.com/duct-framework/core)が弾かれ、これもうわかんねえな。






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

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

## clj-http
[clj-http](https://github.com/dakrone/clj-http)を読み込んだ時に `org.apache.commons.codec.binary.Base64` (java.lang.Class)がシンボル解決エラーで弾かれた。

clj-httpを利用するライブラリ……たとえば [clj-slack](https://github.com/julienXX/clj-slack)も当然読み込めない。

(httpライブラリを使いたければ [borkdude/clj-http-lite](https://github.com/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](https://clojure.org/reference/protocols)機能を使っている時も、第一引数の型をJavaクラス表記で書くとダメみたい。

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

```clojure
(defrecord MyType [element])

(defprotocol MyProtocol
  (sample [type]))

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

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

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

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

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


```bash
$ 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クラスらしいので、何が違うのかはよくわかっていない。