(define -ayalog '())

括弧に魅せられて道を外した名前のないプログラマ

Boot の REPL 上では Clojure の compile 関数は動かない

タイトルまま。
例えばこういう build.boot を書いているとする。

;; build.boot
(set-env! :resource-paths #{"src"}
          :dependencies '[[org.clojure/clojure "1.6.0"]])

さらにこういうファイルを書いているとする。

;; bar.clj
(ns foo.bar)

(gen-class
 :name foo.bar.Baz
 :methods [[piyo [] void]])

(defn -piyo [this]
  (println "Piyo!!"))

そうして REPL を起動して以下を実行する。

boot.user=> (compile 'foo.bar)
CompilerException java.io.IOException: No such file or directory, compiling:(foo/bar.clj:1:1) 

最初何か悪いことしたかなーって思ったけど、そうでもなさそう。ちょっと github の issue で聞いたら「別に aot タスク使えば良くない?」みたいな感じだったのでたぶん boot だと REPL の中で compile 関数は使わない方がいいんだと思う。

boot.user=> (boot (aot :namespace #{'foo.bar}))
boot.user=> (require 'foo.bar :reload)
boot.user=> (.piyo (foo.bar.Baz.))

こうすれば一応実行は出来ますと。ただし、もし bar.clj を修正して aot でリコンパイルしたとしても、残念ながら修正を REPL 上に反映させることができない。

じゃあ、どうしたらいいかというと、以下のように変更監視用の REPL サーバーを設けてあげれば良いですよと。

$ boot watch aot -n foo.bar repl -s wait &

そして REPL クライアントを起動して普通に使えば良いと。

boot.user=> (require 'foo.bar :reload)
boot.user=> (.piyo (foo.bar.Baz.))

こうすれば bar.clj を修正したらそれに自動的に追随してくれるわけですねー。便利。