(. instance-expr instanceFieldName-symbol)
(. Classname-symbol staticFieldName-symbol)
(. instance-expr (instanceMethodName-symbol args*))
(. Classname-symbol (staticMethodName-symbol args*))
Special form.
The '.' special form is the primary access to Java. It can be considered a member-access operator, and/or read as 'in the scope of'.
If the first operand is a symbol that resolves to a class name, the access is considered to be to a static member of the named class. Otherwise it is presumed to be an instance member and the first argument is evaluated to produce the target object.
If the second operand is a symbol it is taken to be a field access - the name of the field is the name of the symbol. The value of the expression is the value of the field.
If the second operand is a list it is taken to be a method call. The first element of the list must be a simple symbol, and the name of the method is the name of the symbol. The args, if any, are evaluated from left to right, and passed to the matching method, which is called, and its value returned. If the method has a void return type, the value of the expression will be nil.
Note that boolean return values will be turned into nil or non-nil, chars will become Characters, and numeric primitives will become Clojure Nums.
(.. instance-expr member+)
(.. Classname-symbol member+)
member => fieldName-symbol or (instanceMethodName-symbol args*)
Macro. Expands into a member access (.) of the first member on the first argument, followed by the next member on the result, etc. For instance:
(.. System (getProperties) (get "os.name"))
expands to:
(. (. System (getProperties)) (get "os.name"))
but is easier to write, read, and understand.
(doto instance-expr (instanceMethodName-symbol args*)*)
Macro. Evaluates instance-expr then calls all of the methods with the supplied arguments in succession on the resulting object, returning it.
(doto (new java.util.HashMap) (put "a" 1) (put "b" 2))
-> {a=1, b=2}
(new Classname-symbol args*)
Special form.
The args, if any, are evaluated from left to right, and passed to the constructor of the class named by the symbol. The constructed object is returned.
(instance? Class expr)
Evaluates expr and tests if it is an instance of the class. Returns true or false
(set! (. instance-expr instanceFieldName-symbol) expr)
(set! (. Classname-symbol staticFieldName-symbol) expr)
Assignment special form.
When the first operand is a field member access form, the assignment is to the corresponding field. If it is an instance field, the instance expr will be evaluated, then the expr.
In all cases the value of expr is returned.
Note - you cannot assign to function params or local bindings. Only Java fields, Vars, Refs and Agents are mutable in Clojure.
(memfn method-name arg-names*)
Macro. Expands into code that creates a fn that expects to be passed an object and any args and calls the named instance method on the object passing the args. Use when you want to treat a Java method as a first-class fn.
(map (memfn charAt i) ["fred" "ethel" "lucy"] [1 2 3])
-> (\r \h \y)
(bean obj)
Takes a Java object and returns a read-only implementation of the map abstraction based upon its JavaBean properties.(bean (. java.awt.Color black))
-> {:RGB -16777216, :alpha 255, :transparency 1,
:class class java.awt.Color, :green 0, :blue 0,
:colorSpace java.awt.color.ICC_ColorSpace@c94b51, :red 0}
Support for Java in Clojure Library Functions
Many of the Clojure library functions have defined semantics for objects of Java types. contains? and get work on Java Maps, arrays, Strings, the latter two with integer keys. count works on Java Strings, Collections and arrays. nth works on Java Strings, Lists and arrays. seq works on Java reference arrays, Iterables and Strings. Since much of the rest of the library is built upon these functions, there is great support for using Java objects in Clojure algorithms.
Implementing Interfaces and Extending Classes
Clojure supports the dynamic creation of objects that implement one or more interfaces and/or extend a class with theproxy macro. The resulting objects are of an anonymous class.
( proxy [class-and-interfaces] [args] fs+)
class-and-interfaces - a vector of class namesargs - a (possibly empty) vector of arguments to the superclass constructor.
f => (name [params*] body) or (name ([params*] body) ([params+] body) ...)
Expands to code which creates a instance of a proxy class that implements the named class/interface(s) by calling the supplied fns. A single class, if provided, must be first. If not provided it defaults to Object. The interfaces names must be valid interface types. If a method fn is not provided for a class method, the superclass methd will be called. If a method fn is not provided for an interface method, an UnsupportedOperationException will be thrown should it be called. Method fns are closures and can capture the environment in which
proxy is called. Each method fn takes an additional implicit first arg, which is bound to this. Note that while method fns can be provided to override protected methods, they have no other access to protected members, nor to super, as these capabilities cannot be proxied.
Arrays
Clojure supports the creation, reading and modification of Java arrays. It is recommended that you limit use of arrays to interop with Java libraries that require them as arguments or use them as return values.(alength array)
Returns the length of the array. Works on arrays of all types.(aget array idx+)
Returns the value at the index/indices. Works on arrays of all types.(aset array idx+ val)
Sets the value at the index/indices. Works on arrays of reference types. Returns val.(aset-int array idx+ val)
(aset-long array idx+ val)
(aset-float array idx+ val)
(aset-double array idx+ val)
(aset-boolean array idx+ val)
(aset-char array idx+ val)
(aset-short array idx+ val)
(aset-byte array idx+ val)
Sets the value at the index/indices. Works on arrays of the specified primitive type. Returns val.(make-array class dim+)
Creates and returns an array of instances of the specified class of the specified dimension(s). Note that a class object is required. Class objects can be obtained by using their imported or fully-qualified name. Class objects for the primitive types can be obtained using, e.g.,(. Integer TYPE).
(to-array coll)
Returns an array of Objects containing the contents of coll, which can be any Collection. Maps to java.util.Collection.toArray().(into-array coll)
Returns an array of the type of the first element in coll, containing the contents of coll, which must be of a compatible type.
user=> (to-array ["fred" "ethel"])
[Ljava.lang.Object;@3f472b
user=> (into-array ["fred" "ethel"])
[Ljava.lang.String;@74e78a
(to-array-2d coll)
Returns a (potentially-ragged) 2-dimensional array of Objects containing the contents of coll, which can be any Collection of any Collection.(aget (to-array-2d [[1][2 3][4 5 6]]) 1 1)
-> 3
Type Hints
Clojure supports the use of type hints to assist the compiler in avoiding reflection in performance-critical areas of code. Normally, one should avoid the use of type hints until there is a known performance bottleneck. Type hints are metadata tags placed on symbols or expressions that are consumed by the compiler. They can be placed on function parameters, let-bound names, var names (when defined), and expressions:
(defn len [x]
(. x (length)))
(defn len2 [#^String x]
(. x (length)))
user=> (time (reduce + (map len (replicate 1000000 "asdf"))))
"Elapsed time: 8315.198 msecs"
4000000
user=> (time (reduce + (map len2 (replicate 1000000 "asdf"))))
"Elapsed time: 1158.045 msecs"
4000000
Once a type hint has been placed on an identifier or expression, the compiler will try to resolve any calls to methods thereupon at compile time. In addition, the compiler will track the use of any return values and infer types for their use and so on, so very few hints are needed to get a fully compile-time resolved series of calls. Note that type hints are not needed for static members (or their return values!) as the compiler always has the type for statics.
There is a *warn-on-reflection* flag (defaults to false) which will
cause the compiler to warn you when it can't resolve to a direct call:
(set! *warn-on-reflection* true)
-> true
(defn foo [s] (. s (charAt 1)))
-> Reflection warning, line: 2 - call to charAt can't be resolved.
-> #user/foo
(defn foo [#^String s] (. s (charAt 1)))
-> #user/foo
Coercions
At times it is necessary to have a value of a particular primitive type. These coercion functions yield a (boxed) value of the indicated type as long as such a coercion is possible:(int x)
(long x)
(float x)
(double x)
(char x)
(boolean x)
(short x)
(byte x)
Simple XML Support
Included with the distribution is simple XML support, found in the src/xml.clj file. All names from this file are in thexml namespace.
(parse source)
Parses and loads the source, which can be a File, InputStream or String naming a URI. Returns a tree of the xml/element struct-map, which has the keys :tag, :attrs, and :content. and accessor fns tag, attrs, and content.
(xml/parse "/Users/rich/dev/clojure/build.xml")
-> {:tag :project, :attrs {:name "clojure", :default "jar"}, :content [{:tag :description, ...