Оновлення : з моменту опублікування цієї відповіді деякі доступні інструменти змінилися. Після оригінальної відповіді з'являється оновлення, що включає інформацію про те, як побудувати приклад за допомогою поточних інструментів.
Це не так просто, як компілювати в банку і викликати внутрішні методи. Здається, є кілька хитрощів, щоб все це працювало. Ось приклад простого файлу Clojure, який можна зібрати в банку:
(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)))
)
Якщо ви запустите його, ви повинні побачити щось на кшталт:
(binomial 5 3): 10
(binomial 10042 111): 49068389575068144946633777...
А ось програма Java, яка викликає -binomial
функцію в 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));
}
}
Його вихід:
(binomial 5 3): 10.0
(binomial 10042, 111): 4.9068389575068143E263
Перший фрагмент магії - це використання :methods
ключового слова у gen-class
виписці. Це, здається, потрібно для отримання доступу до функції Clojure на зразок статичних методів на Java.
Друге - створити функцію обгортки, яку може викликати Java. Зауважте, що друга версія -binomial
має тире перед собою.
І звичайно, сама банка Clojure повинна бути на уроці. У цьому прикладі використано банку Clojure-1.1.0.
Оновлення : Ця відповідь була повторно перевірена за допомогою наступних інструментів:
- Clojure 1.5.1
- Лейнінген 2.1.3
- Оновлення JDK 1.7.0 25
Частина Clojure
Спочатку створіть проект та пов'язану з ним структуру каталогів за допомогою Leiningen:
C:\projects>lein new com.domain.tiny
Тепер перейдіть до каталогу проектів.
C:\projects>cd com.domain.tiny
У каталозі проекту відкрийте project.clj
файл і відредагуйте його таким чином, щоб вміст був таким, як показано нижче.
(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)
Тепер переконайтесь, що всі залежності (Clojure) доступні.
C:\projects\com.domain.tiny>lein deps
Ви можете побачити повідомлення про завантаження банку Clojure в цей момент.
Тепер відредагуйте файл Clojure C:\projects\com.domain.tiny\src\com\domain\tiny.clj
таким чином, щоб він містив програму Clojure, показану в оригінальній відповіді. (Цей файл був створений, коли Leiningen створив проект.)
Велика частина магії тут полягає в оголошенні простору імен. :gen-class
Каже системі , щоб створити клас з ім'ям com.domain.tiny
за допомогою одного методу статичної називається binomial
, функція приймає два цілочисельних аргументу і повертає в два рази. Є дві аналогічно названі функції binomial
, традиційна функція Clojure, -binomial
і обгортка, доступна від Java. Зверніть увагу на дефіс у назві функції -binomial
. Префікс за замовчуванням - дефіс, але за бажанням його можна змінити на щось інше. Ця -main
функція робить кілька викликів до біноміальної функції, щоб переконатися, що ми отримуємо правильні результати. Для цього складіть клас та запустіть програму.
C:\projects\com.domain.tiny>lein run
Ви повинні побачити вихід, показаний у вихідній відповіді.
Тепер упакуйте його в банку і покладіть кудись зручно. Скопіюйте туди також банку 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.
Частина Java
Leiningen має вбудоване завдання, lein-javac
яке має бути в змозі допомогти з компіляцією Java. На жаль, він, здається, порушений у версії 2.1.3. Він не може знайти встановлений JDK і не може знайти сховище Maven. Шляхи до обох мають вбудовані пробіли в моїй системі. Я припускаю, що це проблема. Будь-який Java IDE також може працювати з компіляцією та упаковкою. Але на цій посаді ми переходимо до старої школи і робимо це в командному рядку.
Спочатку створіть файл Main.java
із вмістом, показаним у вихідній відповіді.
Складати частину Java
javac -g -cp target\com.domain.tiny-0.1.0-SNAPSHOT.jar -d target\src\com\domain\Main.java
Тепер створимо файл з деякою метаінформацією, яку слід додати до баночки, яку ми хочемо створити. В Manifest.txt
, додайте наступний текст
Class-Path: lib\com.domain.tiny-0.1.0-SNAPSHOT.jar lib\clojure-1.5.1.jar
Main-Class: Main
Тепер упакуйте все це в один великий файл jar, включаючи нашу програму Clojure та банку 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
Щоб запустити програму:
C:\projects\com.domain.tiny\target>java -jar Interop.jar
(binomial 5 3): 10.0
(binomial 10042, 111): 4.9068389575068143E263
Вихід по суті ідентичний тому, який виробляється лише Clojure, але результат був перетворений в подвійний Java.
Як уже згадувалося, Java IDE, ймовірно, подбає про безладні аргументи компіляції та упаковку.