Atualização : desde que esta resposta foi publicada, algumas das ferramentas disponíveis foram alteradas. Após a resposta original, há uma atualização incluindo informações sobre como criar o exemplo com as ferramentas atuais.
Não é tão simples como compilar em um jar e chamar os métodos internos. Parece haver alguns truques para fazer tudo funcionar. Aqui está um exemplo de um arquivo Clojure simples que pode ser compilado em um jar:
(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 você executá-lo, verá algo como:
(binomial 5 3): 10
(binomial 10042 111): 49068389575068144946633777...
E aqui está um programa Java que chama a -binomial
função no 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));
}
}
Sua saída é:
(binomial 5 3): 10.0
(binomial 10042, 111): 4.9068389575068143E263
A primeira peça de mágica está usando a :methods
palavra - chave na gen-class
declaração. Isso parece ser necessário para permitir que você acesse a função Clojure, como métodos estáticos em Java.
A segunda coisa é criar uma função de invólucro que pode ser chamada pelo Java. Observe que a segunda versão -binomial
tem um traço na frente.
E, é claro, o próprio jar Clojure deve estar no caminho da classe. Este exemplo usou o jar Clojure-1.1.0.
Atualização : Esta resposta foi testada novamente usando as seguintes ferramentas:
- Clojure 1.5.1
- Leiningen 2.1.3
- JDK 1.7.0 Atualização 25
A parte de Clojure
Primeiro, crie um projeto e uma estrutura de diretórios associada usando Leiningen:
C:\projects>lein new com.domain.tiny
Agora, mude para o diretório do projeto.
C:\projects>cd com.domain.tiny
No diretório do projeto, abra o project.clj
arquivo e edite-o para que o conteúdo seja como mostrado abaixo.
(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)
Agora, verifique se todas as dependências (Clojure) estão disponíveis.
C:\projects\com.domain.tiny>lein deps
Você pode ver uma mensagem sobre o download do jar Clojure neste momento.
Agora edite o arquivo Clojure para C:\projects\com.domain.tiny\src\com\domain\tiny.clj
que ele contenha o programa Clojure mostrado na resposta original. (Este arquivo foi criado quando Leiningen criou o projeto.)
Grande parte da mágica aqui está na declaração do espaço para nome. O comando :gen-class
diz ao sistema para criar uma classe nomeada com.domain.tiny
com um único método estático chamado binomial
, uma função que recebe dois argumentos inteiros e retorna um duplo. Existem duas funções com nomes semelhantes binomial
, uma função tradicional do Clojure -binomial
e um wrapper acessível a partir de Java. Observe o hífen no nome da função -binomial
. O prefixo padrão é um hífen, mas pode ser alterado para outra coisa, se desejado. A -main
função apenas faz algumas chamadas para a função binomial para garantir que estamos obtendo os resultados corretos. Para fazer isso, compile a classe e execute o programa.
C:\projects\com.domain.tiny>lein run
Você deve ver a saída mostrada na resposta original.
Agora, embrulhe-o em uma jarra e coloque-o em algum lugar conveniente. Copie o frasco Clojure também.
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.
A parte Java
Leiningen tem uma tarefa interna,, lein-javac
que deve poder ajudar na compilação do Java. Infelizmente, parece estar quebrado na versão 2.1.3. Ele não consegue encontrar o JDK instalado e o repositório Maven. Os caminhos para ambos têm espaços incorporados no meu sistema. Presumo que esse seja o problema. Qualquer IDE Java também pode lidar com a compilação e o empacotamento. Mas para este post, estamos indo para a velha escola e fazendo isso na linha de comando.
Primeiro, crie o arquivo Main.java
com o conteúdo mostrado na resposta original.
Para compilar parte java
javac -g -cp target\com.domain.tiny-0.1.0-SNAPSHOT.jar -d target\src\com\domain\Main.java
Agora crie um arquivo com algumas meta-informações para adicionar ao jar que queremos construir. Em Manifest.txt
, adicione o seguinte texto
Class-Path: lib\com.domain.tiny-0.1.0-SNAPSHOT.jar lib\clojure-1.5.1.jar
Main-Class: Main
Agora empacote tudo em um arquivo jar grande, incluindo nosso programa Clojure e o jar 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
Para executar o programa:
C:\projects\com.domain.tiny\target>java -jar Interop.jar
(binomial 5 3): 10.0
(binomial 10042, 111): 4.9068389575068143E263
A saída é essencialmente idêntica à produzida apenas por Clojure, mas o resultado foi convertido em um Java duplo.
Como mencionado, um Java IDE provavelmente cuidará dos argumentos confusos de compilação e do empacotamento.