-main
中からgen-class
で定義したクラスを呼びだす以下のコードをlein run
で実行しようとするとエラーが発生する.
src/class-ns-test/core.clj
(ns class-ns-test.core)
(gen-class :name "Hello")
;; クラスを作るにはgen-class関数を使うほか, nsの中に:gen-class symbolをkeyとするmappingの形で定義することもできる.
(defn -main [& args]
(println (Class/forName "Hello")))
$ lein run
Exception in thread main java.lang.ClassNotFoundException: Hello
````````
project.cljに:aotオプションを加えるとうまくいく.
```````````clojure:project.clj
(defproject class-ns-test "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.5.1"]]
:aot [class-ns-test.core] ;; <==== 追加
:main class-ns-test.core)
$ lein run
Hello
````````
`:aot` とは何か.
Ahead-of-time Compilation
====================================
[aot = ahead-of-time compilationについての公式ドキュメント](http://clojure.org/compilation) によると
* Clojureはon-the-fly(実行中?)にコードをJVMバイトコードにコンパイルする.
* しかし, 以下の様なケースでは事前に(ahead-of-time)コンパイルしておきたい.
* ソースコードなしでアプリケーションを配布したい
* アプリケーションの起動を速くしたい
* Javaの名前ありクラスを使いたい
* アプリケーションに実行時バイトコード変換が必要ない
aotは以下の様な方針/仕様となっている.
* Clojureの動的性質を出来るだけ失わないように設計されている
* ソースコードと生成される.classパスはJavaのclasspath規約に従う
* コンパイルはnamespace単位で指定
* fnおよびgen-classが, それぞれ1個ずつの.classファイルを生成する
また, compile関数を使うことでコード中の任意の位置でコンパイルすることも出来る. つまりproject.cljに:aotを追加する代わりに, 以下のようにも書ける.
```````clojure:src/class-ns-test/core.clj
(defn -main [& args]
(compile 'class-ns-test.core) ;; <==== 追加
(println (Class/forName "Hello")))
````````