Aggiornamento : da quando è stata pubblicata questa risposta, alcuni degli strumenti disponibili sono cambiati. Dopo la risposta originale, c'è un aggiornamento che include informazioni su come creare l'esempio con gli strumenti attuali.
Non è così semplice come compilare in un barattolo e chiamare i metodi interni. Sembra che ci siano alcuni trucchi per farlo funzionare comunque. Ecco un esempio di un semplice file Clojure che può essere compilato in un vaso:
(ns com.domain.tiny
(:gen-class
:name com.domain.tiny
:methods [#^{:static true} [binomial [int int] double]]))
(defn binomial
"Calculate the binomial coefficient."
[n k]
(let [a (inc n)]
(loop [b 1
c 1]
(if (> b k)
c
(recur (inc b) (* (/ (- a b) b) c))))))
(defn -binomial
"A Java-callable wrapper around the 'binomial' function."
[n k]
(binomial n k))
(defn -main []
(println (str "(binomial 5 3): " (binomial 5 3)))
(println (str "(binomial 10042 111): " (binomial 10042 111)))
)
Se lo esegui, dovresti vedere qualcosa di simile:
(binomial 5 3): 10
(binomial 10042 111): 49068389575068144946633777...
Ed ecco un programma Java che chiama la -binomial
funzione in tiny.jar
.
import com.domain.tiny;
public class Main {
public static void main(String[] args) {
System.out.println("(binomial 5 3): " + tiny.binomial(5, 3));
System.out.println("(binomial 10042, 111): " + tiny.binomial(10042, 111));
}
}
Il suo output è:
(binomial 5 3): 10.0
(binomial 10042, 111): 4.9068389575068143E263
Il primo pezzo di magia sta usando la :methods
parola chiave gen-class
nell'istruzione. Ciò sembra essere necessario per consentire l'accesso alla funzione Clojure in modo simile ai metodi statici in Java.
La seconda cosa è creare una funzione wrapper che può essere chiamata da Java. Si noti che la seconda versione di -binomial
ha un trattino di fronte.
E ovviamente il vaso Clojure stesso deve essere sul percorso di classe. In questo esempio è stato utilizzato il vaso Clojure-1.1.0.
Aggiornamento : questa risposta è stata nuovamente testata utilizzando i seguenti strumenti:
- Clojure 1.5.1
- Leiningen 2.1.3
- Aggiornamento 25.0 JDK 1.7.0
La parte di Clojure
Per prima cosa crea un progetto e la struttura di directory associata usando Leiningen:
C:\projects>lein new com.domain.tiny
Ora passa alla directory del progetto.
C:\projects>cd com.domain.tiny
Nella directory del progetto, apri il project.clj
file e modificalo in modo che il contenuto sia come mostrato di seguito.
(defproject com.domain.tiny "0.1.0-SNAPSHOT"
:description "An example of stand alone Clojure-Java interop"
:url "http://clarkonium.net/2013/06/java-clojure-interop-an-update/"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.5.1"]]
:aot :all
:main com.domain.tiny)
Ora, assicurati che tutte le dipendenze (Clojure) siano disponibili.
C:\projects\com.domain.tiny>lein deps
A questo punto potresti vedere un messaggio sul download del vaso Clojure.
Ora modifica il file Clojure in modo C:\projects\com.domain.tiny\src\com\domain\tiny.clj
tale che contenga il programma Clojure mostrato nella risposta originale. (Questo file è stato creato quando Leiningen ha creato il progetto.)
Gran parte della magia qui è nella dichiarazione dello spazio dei nomi. Il :gen-class
dice al sistema di creare una classe denominata com.domain.tiny
con un metodo statico singolo chiamato binomial
, una funzione di prendere due argomenti interi e restituisce un doppio. Esistono due funzioni con binomial
nomi simili , una funzione Clojure tradizionale -binomial
e un wrapper accessibili da Java. Nota il trattino nel nome della funzione -binomial
. Il prefisso predefinito è un trattino, ma può essere cambiato in qualcos'altro se lo si desidera. La -main
funzione effettua solo un paio di chiamate alla funzione binomiale per assicurare che stiamo ottenendo i risultati corretti. Per fare ciò, compila la classe ed esegui il programma.
C:\projects\com.domain.tiny>lein run
Dovresti vedere l'output mostrato nella risposta originale.
Ora impacchettalo in un barattolo e mettilo in un posto comodo. Copia lì anche il barattolo Clojure.
C:\projects\com.domain.tiny>lein jar
Created C:\projects\com.domain.tiny\target\com.domain.tiny-0.1.0-SNAPSHOT.jar
C:\projects\com.domain.tiny>mkdir \target\lib
C:\projects\com.domain.tiny>copy target\com.domain.tiny-0.1.0-SNAPSHOT.jar target\lib\
1 file(s) copied.
C:\projects\com.domain.tiny>copy "C:<path to clojure jar>\clojure-1.5.1.jar" target\lib\
1 file(s) copied.
La parte Java
Leiningen ha un'attività integrata lein-javac
, che dovrebbe essere in grado di aiutare con la compilazione Java. Sfortunatamente, sembra essere rotto nella versione 2.1.3. Non riesce a trovare il JDK installato e non trova il repository Maven. I percorsi per entrambi hanno spazi incorporati sul mio sistema. Presumo che sia questo il problema. Qualsiasi IDE Java potrebbe gestire anche la compilazione e il packaging. Ma per questo post, andiamo alla vecchia scuola e lo facciamo dalla riga di comando.
Innanzitutto crea il file Main.java
con i contenuti mostrati nella risposta originale.
Per compilare la parte Java
javac -g -cp target\com.domain.tiny-0.1.0-SNAPSHOT.jar -d target\src\com\domain\Main.java
Ora crea un file con alcune meta-informazioni da aggiungere al vaso che vogliamo costruire. In Manifest.txt
, aggiungi il seguente testo
Class-Path: lib\com.domain.tiny-0.1.0-SNAPSHOT.jar lib\clojure-1.5.1.jar
Main-Class: Main
Ora impacchettalo in un unico grande file jar, incluso il nostro programma Clojure e il vaso Clojure.
C:\projects\com.domain.tiny\target>jar cfm Interop.jar Manifest.txt Main.class lib\com.domain.tiny-0.1.0-SNAPSHOT.jar lib\clojure-1.5.1.jar
Per eseguire il programma:
C:\projects\com.domain.tiny\target>java -jar Interop.jar
(binomial 5 3): 10.0
(binomial 10042, 111): 4.9068389575068143E263
L'output è essenzialmente identico a quello prodotto da Clojure da solo, ma il risultato è stato convertito in un doppio Java.
Come accennato, un IDE Java si occuperà probabilmente degli argomenti di compilazione disordinati e del packaging.