Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Options for creating Java classes in Clojure

There are a few different ways to create Java classes in Clojure, so what are the tradeoffs when picking between gen-class, proxy, and reify in Clojure? (are there other ways to create Java classes that I haven't listed?)

My basic understanding is that I have listed these constructs in decreasing order of power.

like image 994
pauldoo Avatar asked Apr 29 '11 11:04

pauldoo


People also ask

Can clojure use Java libraries?

Clojure programs get compiled to Java bytecode and executed within a JVM process. Clojure programs also have access to Java libraries, and you can easily interact with them using Clojure's interop facilities.

Are there classes in Clojure?

Clojure has gen-class, reify, proxy and also deftype and defrecord to define new class-like datatypes. For a language that values syntactic simplicity and abhors unnecessary complexity, it seems like an aberration.

What does gen class do in Clojure?

The generated class automatically defines all of the non-private methods of its superclasses/interfaces. This parameter can be used to specify the signatures of additional methods of the generated class.

Is clojure interoperable with Java?

Overview. Clojure was designed to be a hosted language that directly interoperates with its host platform (JVM, CLR and so on). Clojure code is compiled to JVM bytecode. For method calls on Java objects, Clojure compiler will try to emit the same bytecode javac would produce.


2 Answers

Use gen-class when you want a named class or you want to add new methods to objects you create. gen-class relies on AOT compilation.

When you want an anonymous, one-off implementation of a type you use reify or proxy. They do not rely on AOT compilation. Here are their differences:

  1. reify only supports protocols or interfaces, proxy also supports concrete superclasses.
  2. reify uses true class methods, proxy uses external functions.
  3. Because of #2, reify uses direct method lookup, while proxy uses a map for method lookup.
  4. Because of #3, reify does not support dynamic swapping of methods, but proxy does.

reify will perform better than proxy, so you should always use reify when possible. Only use proxy when reify's constraints are too prohibitive.

like image 170
dbyrne Avatar answered Sep 27 '22 09:09

dbyrne


In addition to gen-class, proxy and reify, we have defrecord and deftype. These latter two options should be your first choices for the creation of named java classes (and in the case of defrecord, your first choice for any kind of struct with named components.)

The datatypes page on clojure.org is a good reference on this topic. Defrecord, deftype and reify are newer than gen-class and proxy, having been introduced in version 1.2 (I think -- possibly 1.1). Defrecord and deftype both create classes that conform to interfaces, but do not allow for inheritance. If you need inheritance, gen-class (and proxy for anonymous classes) is still your only option.

Defrecord and deftype differ in what you are given for free. Defrecord automatically creates a class which conforms to IPersistentMap and ISeq. Deftype, on the other hand, gives you more control over your class, even allowing for mutable fields (not allowed in defrecord). In general, deftype is intended for low-level implementation of data structures, whereas defrecord is intended for most day-to-day use.

like image 20
Rob Lachlan Avatar answered Sep 24 '22 09:09

Rob Lachlan