Pembaruan : Karena jawaban ini diposting, beberapa alat yang tersedia telah berubah. Setelah jawaban asli, ada pembaruan termasuk informasi tentang cara membangun contoh dengan alat saat ini.
Ini tidak sesederhana mengkompilasi ke stoples dan memanggil metode internal. Tampaknya ada beberapa trik untuk membuat semuanya bekerja. Berikut adalah contoh file Clojure sederhana yang dapat dikompilasi ke stoples:
(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)))
)
Jika Anda menjalankannya, Anda akan melihat sesuatu seperti:
(binomial 5 3): 10
(binomial 10042 111): 49068389575068144946633777...
Dan inilah program Java yang memanggil -binomial
fungsi dalam 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));
}
}
Outputnya adalah:
(binomial 5 3): 10.0
(binomial 10042, 111): 4.9068389575068143E263
Bagian pertama sihir menggunakan :methods
kata kunci dalam gen-class
pernyataan. Tampaknya diperlukan untuk membiarkan Anda mengakses sesuatu fungsi Clojure seperti metode statis di Jawa.
Hal kedua adalah membuat fungsi wrapper yang bisa dipanggil oleh Java. Perhatikan bahwa versi kedua -binomial
memiliki tanda hubung di depannya.
Dan tentu saja toples Clojure sendiri harus berada di jalur kelas. Contoh ini menggunakan stoples Clojure-1.1.0.
Pembaruan : Jawaban ini telah diuji ulang menggunakan alat berikut:
- Clojure 1.5.1
- Leiningen 2.1.3
- JDK 1.7.0 Pembaruan 25
Bagian Clojure
Pertama buat proyek dan struktur direktori terkait menggunakan Leiningen:
C:\projects>lein new com.domain.tiny
Sekarang, ubah ke direktori proyek.
C:\projects>cd com.domain.tiny
Dalam direktori proyek, buka project.clj
file dan edit sedemikian rupa sehingga isinya seperti yang ditunjukkan di bawah ini.
(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)
Sekarang, pastikan semua dependensi (Clojure) tersedia.
C:\projects\com.domain.tiny>lein deps
Anda mungkin melihat pesan tentang mengunduh botol Clojure pada saat ini.
Sekarang edit file Clojure C:\projects\com.domain.tiny\src\com\domain\tiny.clj
sedemikian rupa sehingga berisi program Clojure yang ditunjukkan dalam jawaban asli. (File ini dibuat ketika Leiningen menciptakan proyek.)
Banyak keajaiban di sini adalah dalam deklarasi namespace. The :gen-class
memberitahu sistem untuk membuat sebuah kelas bernama com.domain.tiny
dengan metode statis tunggal yang disebut binomial
, fungsi mengambil dua argumen integer dan mengembalikan ganda. Ada dua fungsi yang sama bernama binomial
, fungsi Clojure tradisional, dan -binomial
dan pembungkus dapat diakses dari Jawa. Perhatikan tanda hubung dalam nama fungsi -binomial
. Awalan default adalah tanda hubung, tetapi dapat diubah ke sesuatu yang lain jika diinginkan. The -main
Fungsi hanya membuat beberapa panggilan ke fungsi binomial untuk memastikan bahwa kita mendapatkan hasil yang benar. Untuk melakukan itu, kompilasi kelas dan jalankan program.
C:\projects\com.domain.tiny>lein run
Anda akan melihat output yang ditunjukkan pada jawaban asli.
Sekarang bungkus dalam wadah dan taruh di tempat yang nyaman. Salin toples Clojure di sana juga.
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.
Bagian Jawa
Leiningen memiliki tugas bawaan lein-javac
,, yang seharusnya dapat membantu kompilasi Java. Sayangnya, tampaknya rusak di versi 2.1.3. Itu tidak dapat menemukan JDK yang diinstal dan tidak dapat menemukan repositori Maven. Jalur untuk keduanya telah menyematkan ruang pada sistem saya. Saya berasumsi bahwa itulah masalahnya. Setiap IDE Java dapat menangani kompilasi dan pengemasan juga. Tetapi untuk posting ini, kita akan menjadi sekolah tua dan melakukannya di baris perintah.
Pertama buat file Main.java
dengan konten yang ditunjukkan dalam jawaban asli.
Untuk mengkompilasi bagian java
javac -g -cp target\com.domain.tiny-0.1.0-SNAPSHOT.jar -d target\src\com\domain\Main.java
Sekarang buat file dengan beberapa informasi meta untuk ditambahkan ke toples yang ingin kita buat. Di Manifest.txt
, tambahkan teks berikut
Class-Path: lib\com.domain.tiny-0.1.0-SNAPSHOT.jar lib\clojure-1.5.1.jar
Main-Class: Main
Sekarang kemas semuanya ke dalam satu file jar besar, termasuk program Clojure kami dan stoples 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
Untuk menjalankan program:
C:\projects\com.domain.tiny\target>java -jar Interop.jar
(binomial 5 3): 10.0
(binomial 10042, 111): 4.9068389575068143E263
Output dasarnya identik dengan yang diproduksi oleh Clojure saja, tetapi hasilnya telah dikonversi menjadi Java double.
Seperti yang disebutkan, Java IDE mungkin akan menangani argumen kompilasi yang berantakan dan pengemasannya.