Fortunately, Clojure is much easier to use in a mixed Java/Clojure environment than C and C++ were in a mixed Java/C++ environment. Millions of lines of Java code have been written by thousands of programmers for more than the past 20 years. Java interoperability is one of the strongest properties of Clojure and one of the most important areas to understand.
Since Clojure runs on the JVM, it has access to all of Java's rich class library and thousands of open-source libraries developed in Java over the past 20 years. For example, you can create a Java collection and use many of the same functions you would use on any of the built-in Clojure collection types.
First import the class.
user=> (import [java.util.HashSet])
nil
Then create an instance of the class using the new function
user=> (def mySet (new java.util.HashSet))
#'user/mySet
To use any of the member functions, call them as you would a standard Clojure function, but with the function name preceded by a single dot.
user=> (.size mySet)
0
user=> (.add mySet 5)
true
user=> (.add mySet 7)
true
user=> (.add mySet 5)
false
user=> (.size mySet)
2
You can use functions like map and filter on the resulting instance, just as you would for any other Clojure collection.
user=> (map even? mySet)
(false false)
user=> (.add mySet 2)
true
user=> (.add mySet 3)
true
user=> (filter even? mySet)
(2)
user=> (filter odd? mySet)
(3 5 7)
user=> (map (fn [x] (* x x) ) mySet)
(4 9 25 49)
The Clojure built-in types support standard Java interfaces or the standard boxed versions of the Java primitives. You can use the
instance? function in Clojure to verify this.
user=> (instance? Integer 3)
true
user=> (instance? Double 3.0)
true
user=> (instance? Float 3.0)
false
user=> (instance? java.util.Set #{})
true
user=> (instance? java.util.List [])
true
user=> (instance? java.util.Map {})
true
So if your Java function uses interface arguments like this:
public void functionTest(Map m, List l, Set x){...}
instead of classes like this:
public void functionTest(HashMap m, ArrayList l, HashSet x){...}
you can simply create the built-in Clojure types, use the powerful set of functions for those types and call your Java functions without any Java-specific classes inside your Clojure code. You can also use Clojure collections in place of Java generic collections, without the compile time type safety.
Because of the auto-boxing included as part of Java 1.5, you can pass Clojure integers, doubles and doubles into Java functions that use Java primitive type arguments.
Clojure provides a set of functions to create and manipulate Java arrays. To build an array, of a provided type and size, use the make-array function.
user=> (def array (make-array (. Integer TYPE) 5))
#'user/array
user=> array
#
user=>
You can also use the to-array function to convert an existing Clojure collection into an array.
user=> (def setArray (to-array #{1 2 3 4}))
#'user/setArray
user=> setArray
#Note that this created an array of Objects. If you want to create arrays of a specific type, use the into-array function.
user=> (def setArrayOfInts (into-array #{1 2 3 4}))
#'user/setArrayOfInts
user=> setArrayOfInts
#
user=>
1 comment:
Small correction:
(import [java.util.HashSet])
should be:
(import '(java.util HashSet))
Post a Comment