Yes, this is a way of how you allow java
to call clojure
code.
If you create, for example, lein new app testapp
(lein
is command line interface for leiningen
a widely used clojure projects automation tool) you may see in your core.clj a line
(ns testapp.core
(:gen-class))
(defn -main
"Comment line"
[&args]
(println "Hello, World!"))
Here ns
is a macro that makes easier to define namespaces and other things.
Important thing here is (:gen-class)
. Let unwrap the macro:
> (macroexpand-1 '(ns testapp.core (:gen-class)))
(do
....
(clojure.core/gen-class :name "testapp.core" :impl-ns testapp.core :main true)
....)
This code will tell the compiler to generate the byte code for the class named "testapp.core" and this class marked as ":main true". This mark will create a declaration of static public main
function in the class, so jvm
could start a program calling the main
function. By java language convention the program entry point should be called main
. You can add different methods to gen-class
(see docs) declaring types or arguments and return value, but, as I can assume, it can be useful to separate java
statically typed methods from your clojure
functions to prevent name collapse. So gen-class
allows you to define a :prefix
that you use to name your java class implementation. Default one is "-". So you create a function -main
and in java
code it would look like testapp.core.main
.
We can change it
(ns testapp.core
(:gen-class :prefix my-prefix-))
When you compile your code to jar and run with java -jar
you get
Exception in thread "main" java.lang.UnsupportedOperationException:
testapp.core/my-prefix-main not defined
Ok, we forgot to rename our implementation:
(defn my-prefix-main [&args] (println "Hello, World!"))
Compile and run:
"Hello, World!"
P. S. I can't tell you about naming conventions of protocols and interfaces that are used in clojure
.